Autor Beitrag
galagher
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: So 18.01.15 19:31 
Hallo!

Man kann ja eine Variable im Private-Abschnitt deklarieren, zB. für MDI-Forms. Der Zweck ist klar, sie gilt dann nur für das jeweilige MDIChild.

Nun erzeuge ich aber keine MDI-Forms, sondern Komponenten zur Laufzeit. So, wie man das halt macht: MyKomponente := TWasweissIch.Create(Self). Jetzt brauche ich für jede dieser Komponenten eine spezielle, nur für diese Komponente geltende Variable, die ich aber dennoch global in Form1 verwenden können muss. Das bedeutet, wenn eine dieser Komponenten den Fokus hat, man also mit ihr arbeitet, und ich spreche "ihre" Variable an, soll das keine Auswirkungen auf die gleichartigen Variablen der anderen Komponenten haben.

Frage: Wie mache ich das?

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19274
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 18.01.15 20:11 
Das hört sich so an als wäre eine eigene abgeleitete Klasse dieser Komponente das Richtige, damit du dort ein solches Feld unterbringen kannst. Das würde ich hier sehr empfehlen.

Wenn du über die Komponente auf deine Variable zugreifen willst, könntest du auch ein TDictionary<TYourComponent, TYourField> benutzen. Das halte ich aber für nicht so sauber im Vergleich zu der anderen Lösung.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: So 18.01.15 20:25 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das hört sich so an als wäre eine eigene abgeleitete Klasse dieser Komponente das Richtige, damit du dort ein solches Feld unterbringen kannst.
Das habe ich mir zuerst auch gedacht, scheue aber den Aufwand! :?
Einfachere Lösung: Ich füge die Variable in den Quelltext der Komponente unter public ein, so kann ich auf sie zugreifen. Ist nicht sauber, aber geht. Naja, geht nur mit weiteren Tricks im Quelltext von Form1, scheint aber bisher zu funktionieren.

Konkret: Undo/Redo für TJvWideHLEditor, hatte das hier schon mal angefragt, mit MDI klappt das:
www.entwickler-ecke....8&highlight=undo
Undo/Redo: [url]development.mwcs.de/tutundoredo.html[/url]

Ich machte dann die Titelleiste der MDI's weg: www.entwickler-ecke....ewtopic.php?t=113837, dann kam es zu einem Fehler beim Erstellen des Fenster-Gerätekontexts. Also dachte ich, ich programmiere alles ohne MDI neu. Jetzt habe ich eine TabBar, jedes Tab hat eine TJvWideHLEditor-Komponente. Dann wurde mir klar, dass jede Komponente eine eigene Variable braucht.

Abgeleitete Klasse dieser Komponente - gut, werde ich wohl hinbekommen, aber wo gehört da korrekterweise die Variable hin? So wie ich es jetzt habe, scheint es zu funktionieren, aber es ist halt ein Murks...

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: So 18.01.15 20:59 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
MyKomponente := TWasweissIch.Create(Self)					

:mrgreen:
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Jetzt brauche ich für jede dieser Komponenten eine spezielle, nur für diese Komponente geltende Variable, die ich aber dennoch global in Form1 verwenden können muss.

Das klingt mir stark nach einer Instanz-Property. Einfachste Variante:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
type
  TDeineKomponente = class(TVorfahr)
  private
    FDeinFeld: DeinDatentyp;
    ...
  public
    property DeinFeld: DeinDatentyp read FDeinFeld write FDeinFeld;
    ...
  end;

Lässt Du das write weg, hast Du eine ReadOnly-Property, d.h. sie kann von außen nicht verändert werden. Soll sie verändert werden können und Du willst bei einer Änderung noch irgend etwas tun oder diese ggf. sogar ganz verhindern, brauchst Du eine Setter-Methode, das sähe dann z.B. so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
type
  TDeineKomponente = class(TVorfahr)
  private
    FDeinFeld: DeinDatentyp;
    procedure SetDeinFeld(const Value: DeinDatentyp);
    ...
  public
    property DeinFeld: DeinDatentyp read FDeinFeld write SetDeinFeld;
    ...
  end;

...

procedure TDeineKomponente.SetDeinFeld(const Value: DeinDatentyp);
begin
  if Value <> FDeinFeld then
    begin
      FDeinFeld := Value;
      Invalidate;
    end;
end;

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: So 18.01.15 21:17 
user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
MyKomponente := TWasweissIch.Create(Self)					

:mrgreen:
Ja, mein Fehler, korrekt ist natürlich: MyKomponente := TWasWeißDennIch.Create(Self) :mrgreen:

Ok, danke erstmal für deine Beispiele. Wenn ich es so mache, wäre es natürlich sinnvoll, gleich auch den ganzen Undo/Redo-Code :hair: da reinzupacken, dann ist das alles in einem Paket. Ob ich das hinbekomme? :nixweiss: Noch dazu, wo da ein Timer benötigt wird.

Und das alles nur, weil TJvWideHLEditor kein Redo hat. Ob ich mir das antue? Also, als Lernprojekt wäre das schon gut!

Habe ja schon ein paar Komponenten entwickelt, aber fremden Code einbauen, ich weiss nicht...

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
ub60
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 762
Erhaltene Danke: 127



BeitragVerfasst: So 18.01.15 21:52 
Eventuell brauchst Du gar nichts so Kompliziertes. Jede Komponente besitzt eine Eigenschaft "Tag", die Du eventuell für Deine Zwecke "missbrauchen" kannst.

Aus der Hilfe:
Zitat:
Beschreibung

Tag hat keine vordefinierte Bedeutung. Die Eigenschaft Tag steht zur freien Benutzung durch Entwickler zur Verfügung. Sie können in dieser Eigenschaft zusätzliche Informationen über die Komponente in Form einer Ganzzahl speichern oder die Eigenschaft in einen 32-Bit-Wert, wie z.B. in eine Komponentenreferenz oder einen Zeiger, umgewandelt werden.

ub60
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19274
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 19.01.15 06:15 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Das habe ich mir zuerst auch gedacht, scheue aber den Aufwand! :?
Einfachere Lösung: Ich füge die Variable in den Quelltext der Komponente unter public ein, so kann ich auf sie zugreifen.
Noch höher ist der Aufwand, wenn du dann die Komponenten einmal aktualisieren möchtest. ;-)
Denn da du den Quelltext der Komponente angepasst hast, musst du deine Änderungen jedes Mal in die aktuelle Version wieder einbauen...

Aber wo ist das ein großer Aufwand? Du erstellst einfach deine abgeleitete Klasse statt der Standardklasse. Du musst ja nichts registrieren oder irgendwas, da du die Klasse ohnehin manuell erstellst!
Also einfach nur das Feld in die neue Klasse rein wie user profile iconWasWeißDennIch geschrieben hat, die Unit unter uses schreiben und beim Erstellen und in Variablentypen überall die neue Klasse statt der bisherigen nutzen.

user profile iconub60 hat folgendes geschrieben Zum zitierten Posting springen:
Eventuell brauchst Du gar nichts so Kompliziertes. Jede Komponente besitzt eine Eigenschaft "Tag", die Du eventuell für Deine Zwecke "missbrauchen" kannst.
Das sollte man nur machen, wenn man keine andere Möglichkeit hat, sprich in diesem Fall sehe ich keinen Sinn darin das so zu machen. Wenn man dann mal vergisst, dass man die Eigenschaft schon einmal verwendet hat, wundert man sich später und sucht ggf. lange nach dem Fehler. ;-)

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Mo 19.01.15 18:51 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Aber wo ist das ein großer Aufwand? Du erstellst einfach deine abgeleitete Klasse statt der Standardklasse. Du musst ja nichts registrieren oder irgendwas, da du die Klasse ohnehin manuell erstellst!
Also einfach nur das Feld in die neue Klasse rein wie user profile iconWasWeißDennIch geschrieben hat, die Unit unter uses schreiben und beim Erstellen und in Variablentypen überall die neue Klasse statt der bisherigen nutzen.

Klappt! Wobei ich den public-Abschnitt mit der property gar nicht brauche:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
type
  TWideHLEditorX = class(TJvWideHLEditor)
  private
    FUndoRedo: IUndoRedo;
  end;

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19274
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 19.01.15 20:50 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Klappt! Wobei ich den public-Abschnitt mit der property gar nicht brauche:
Solange du nicht von außerhalb der Klasse darauf zugreifst, nicht, nein.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Mo 19.01.15 21:04 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Solange du nicht von außerhalb der Klasse darauf zugreifst, nicht, nein.

Nein, die Variable FUndoRedo wird nur in der Klasse benötigt, zB.
ausblenden Delphi-Quelltext
1:
2:
  TWideHLEditorX(FindComponent(
    'aWideHLEditorX'+IntToStr(JvTabBar1.SelectedTab.Tag))).FUndoRedo.Undo;

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19274
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 19.01.15 22:01 
Bei der Verwendung ist die Verwendung des privaten Felds von außerhalb extrem schlechter Programmierstil. Da solltest du besser eine Property nutzen.

Am besten packst du solche Klassen jeweils in eine eigene Unit, dann kann es auch nicht passieren, dass man private Felder von außen anspricht.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Mo 19.01.15 22:57 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Bei der Verwendung ist die Verwendung des privaten Felds von außerhalb extrem schlechter Programmierstil. Da solltest du besser eine Property nutzen.

Am besten packst du solche Klassen jeweils in eine eigene Unit, dann kann es auch nicht passieren, dass man private Felder von außen anspricht.

Dann sollte ich am Besten gleich eine eigene Unit basteln, mit Register, und auch versuchen, den ganzen Undo/Redo-Kram, der jetzt in separaten Units vorliegt, da reinzupacken...
Ansonsten: Wenn ich es so lasse, wie du vorschlägst, wo muss die Variable dann hin? Sie muss ausschliesslich nur für die jeweilige Komponente gelten ("privat" sein), da sonst das Undo/Redo auch versucht, auf die andere Komponenten zu wirken, was ja nicht erwünscht ist.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19274
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 20.01.15 07:32 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Ansonsten: Wenn ich es so lasse, wie du vorschlägst, wo muss die Variable dann hin? Sie muss ausschliesslich nur für die jeweilige Komponente gelten ("privat" sein), da sonst das Undo/Redo auch versucht, auf die andere Komponenten zu wirken, was ja nicht erwünscht ist.
Das hast du falsch verstanden glaube ich. Die property unter public ist schon richtig. Das wird auch in den ganzen Komponenten, die du nutzt, so benutzt.
Private bezieht sich auf die Sichtbarkeit, das hat nichts mit Klassenfeldern oder ähnlichem zu tun.

Sprich alles unter private kann nur von innerhalb der gleichen Klasse (und leider auch der gleichen Unit) benutzt werden und alles unter public auch von anderen Units aus. Das ändert aber nichts daran, dass das Feld zu der aktuellen Instanz der Klasse gehört. Sprich wenn du mehrere solcher Objekte hast, sind dessen Felder auch unabhängig voneinander, egal ob sie unter private, public, protected oder published stehen.

Anders sieht es mit Klassenfeldern, Klasseneigenschaften und Klassenmethoden aus. Die funktionieren unabhängig von einer konkreten Instanz und sind daher immer nur einmal vorhanden:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
type
  TExample = class
  private
    class var
      FTest: Integer;
  public
    class property Test: Integer read FTest write FTest;
  end;
Das ist wohl das wie du es gedacht hast. Aber das passiert nur, wenn du eine class var oder class property deklarierst.
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Di 20.01.15 09:26 
Wenn das für jede Instanz separat gelten soll (so habe ich es verstanden), ist eine Klassenproperty aber genau der falsche Weg.
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Di 20.01.15 11:10 
user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
Wenn das für jede Instanz separat gelten soll (so habe ich es verstanden), ist eine Klassenproperty aber genau der falsche Weg.

Also doch so?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
type
  TDeineKomponente = class(TVorfahr)
  private
    FDeinFeld: DeinDatentyp;
    ...
  public
    property DeinFeld: DeinDatentyp read FDeinFeld write FDeinFeld;
    ...
  end;

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Di 20.01.15 11:16 
Wenn Du keine Schnittstelle nach außen brauchst, kannst Du die Property auch ersatzlos streichen, so dass nur das private Feld übrig bleibt. Der Casus knacktus ist jetzt, ob jede Instanz ihr eigenes Feld braucht, das nur innerhalb der jeweiligen Instanz gültig ist, oder ob alle Instanzen auf dasselbe Feld zugreifen sollen. Wenn Ersteres, dann hast Du es oben schon richtig skizziert, ansonsten muss es eine Klassenvariable sein.
Stundenplan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 128
Erhaltene Danke: 32

Win 7
Delphi 7 Pers., C# (VS 2010 Express)
BeitragVerfasst: Di 20.01.15 11:21 
@jaenicke: strict private gibt es ja auch noch, das unterbindet willkürlichen Zugriff aus derselben Unit.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19274
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 20.01.15 14:09 
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Also doch so?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
type
  TDeineKomponente = class(TVorfahr)
  private
    FDeinFeld: DeinDatentyp;
    ...
  public
    property DeinFeld: DeinDatentyp read FDeinFeld write FDeinFeld;
    ...
  end;
Ja, genau.

Ich hatte mich etwas missverständlich ausgedrückt fällt mir auf. :oops: Mit "Das ist wohl das wie du es gedacht hast." meinte ich nicht was du wolltest, sondern was du offenbar dachtest was der Quelltext von user profile iconWasWeißDennIch macht.

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2510
Erhaltene Danke: 44

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Di 20.01.15 19:08 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile icongalagher hat folgendes geschrieben Zum zitierten Posting springen:
Also doch so?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
type
  TDeineKomponente = class(TVorfahr)
  private
    FDeinFeld: DeinDatentyp;
    ...
  public
    property DeinFeld: DeinDatentyp read FDeinFeld write FDeinFeld;
    ...
  end;
Ja, genau.
Ok, jetzt habe ich es so wie im Beispiel, um den direkten Zugriff auf die private-Variable vermeiden zu können.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!