Autor Beitrag
jackle32
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 7

Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
BeitragVerfasst: Di 07.01.14 01:03 
Hallo zusammen,

ich bin gerade dabei ein Programm mit mehreren Forms zu schreiben.
Damit die Forms Daten austauschen können habe ich sie gegenseitig bekannt gemacht indem ich in die Hauptunit (Unit1) bei Interface uses die zweite Unit (Unit2) hinzugefügt habe. Bei Unit2 habe ich die Unit1 bei den uses im implementation Teil eingefügt (Hoffe soweit ist das richtig, bin mir da nicht so ganz sicher ob das saubere Programmierung ist). In beiden Units gibt es eine Instanz von TForm, Form1 und Form2 genannt.

Dadurch ist es jetzt ja möglich in Unit2 auf Funktionen des Form1 in Unit1 zuzugreifen. Was auch gut ist, dass ich ja nur die Funktionen im public Teil sehe, die Funktionen in private sind nicht sichtbar. Soweit so gut.
Jetzt ist mir aber aufgefallen, dass ich ja in Unit2 auch alle Komponenten von Form1 sehe. Also alle Edits, Labels, usw. Gibt es die Möglichkeit diese auch zu "verstecken"? Ich will ja, dass ich nur über eine definierte Funktionen Daten an Form1 senden kann.
Hab schon versucht alles in private zu setzen, nur dann startet meine Anwendung gar nicht mehr.

Hoffe auf eure Erfahrung!

Gruß,
Jack

_________________
Es gibt keine dummen Fragen, nur dumme Antworten.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19322
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 07.01.14 09:59 
Du solltest immer nur in eine Richtung direkt zugreifen. Die andere Richtung sollte ausschließlich durch Properties oder Events passieren.

Nimm einfach einmal einen normalen Button. Der greift ja auch nicht auf dein Formular zu, wenn er geklickt wird, sondern du sagst ihm, dass bei OnClick eine bestimmte Methode deines Formulars aufgerufen werden soll. Der Button muss daher dein Formular nicht kennen.
Und wo der Button intern z.B. die Caption speichert interessiert dich wiederum nicht. Du schreibst das einfach in die Property Caption.

Das Prinzip kannst du genauso auch mit den Formularen umsetzen. Wenn das aufrufende Formular direkt auf etwas reagieren soll, löst du ein Event im zweiten Formular aus. Wenn das erste Formular Daten aus dem zweiten holen oder dort setzen soll, benutzt du eine Property.

Für diesen Beitrag haben gedankt: jackle32
vagtler
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 96
Erhaltene Danke: 24


Delphi 2010, C# (VS 2012), Objective-C, Java
BeitragVerfasst: Di 07.01.14 11:04 
Grundsätzlich ist das wohl ein Fall für den Einsatz einer Fassade.


Zuletzt bearbeitet von vagtler am Di 07.01.14 11:06, insgesamt 3-mal bearbeitet
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Di 07.01.14 12:36 
user profile iconvagtler hat folgendes geschrieben Zum zitierten Posting springen:
Grundsätzlich ist das wohl ein Fall für den Einsatz einer Fassade.
Hihi.

@user profile iconjaenicke: das will user profile iconjackle32 ja (bzw. tut es schon). Er möchte es nur erzwingen.
Könnte man mit Interfaces tun, wenn man das unbedingt muss. Ich werde aber nie verstehen (hey, ich hab das nicht studiert, okay?), warum man Dinge formalisieren muss die komplett selbstverständlich sind. An dieser Stelle: als Delphi-Entwickler sollte man wissen, dass man nicht von außen auf Formularvariablen zugreift, egal wie die deklariert sind :nixweiss:

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Di 07.01.14 12:41 
Wenn man die Daten von der Darstellung trennt, könnte man deren Deklaration in eine eigene Unit auslagern, die dann von allen beteiligten Fomularunits eingebunden wird. Diese bekommen dann halt noch eine Property des Typs, die das aufrufende Formular dann belegt. Oder man geht noch weiter in Richtung MVC, dann kennen sich die Formulare gar nicht mehr gegenseitig, sondern der Controller händelt das entsprechend. Ob man diesen Aufwand allerdings auf sich nehmen möchte, hängt von div. Faktoren wie z.B. der Projektgröße ab.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19322
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 07.01.14 14:09 
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
@user profile iconjaenicke: das will user profile iconjackle32 ja (bzw. tut es schon). Er möchte es nur erzwingen.
Das hast du falsch verstanden. Im Moment werden Unit 1 und Form1 direkt aus Unit 2 heraus angesprochen.
user profile iconjackle32 hat folgendes geschrieben Zum zitierten Posting springen:
Bei Unit2 habe ich die Unit1 bei den uses im implementation Teil eingefügt
[...]
Dadurch ist es jetzt ja möglich in Unit2 auf Funktionen des Form1 in Unit1 zuzugreifen
Und das ist ein No-Go.
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Di 07.01.14 16:11 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das hast du falsch verstanden.
Oh, stimmt, da hat er mich mit den vielsagenden Unit- und Formnamen verwirrt :-P
Dann hast du natürlich recht, das wäre erstmal wichtiger als die Frage ob Komponenten private sind oder nicht.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
jackle32 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 7

Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
BeitragVerfasst: Di 07.01.14 20:45 
Hallo zusammen,

soweit schon mal danke. Mir haben sich ja auch die Nackenhaare aufgestellt als ich mich auf einmal schreiben sah:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm2.BtnSpeichernClick(Sender: TObject);
begin
  Form1.Aktualisieren;
end;


Mir ist nur leider kein Ausweg eingefallen. :oops: :roll:

So jetzt habe ich in meinem Form2 ein Event erstellt. Funktioniert grundsätzlich auch schon alles. Ich habe jetzt nur das Problem, wo ich in Form1 am Besten dem Event die Funktion zuweise.

Hier mal die Deklaration des Events:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
TAktualisierenEvent = procedure(Daten: TStringList) of object;

  TForm2 = class(TForm)
    TreeView1: TTreeView;
    PCEinstellungen: TPageControl;
    BtnSpeichern: TButton;
    BtnAbbrechen: TButton;
    TSEinstellungen: TTabSheet;
    TSPfade: TTabSheet;
    TSKonstanten: TTabSheet;
    Edit1: TEdit;
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure BtnSpeichernClick(Sender: TObject);
    procedure BtnAbbrechenClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FOnAktualisieren: TAktualisierenEvent;
    Daten: TStringList;
  public
    property OnAktualisieren: TAktualisierenEvent read FOnAktualisieren write FOnAktualisieren;
  end;

procedure TForm2.BtnSpeichernClick(Sender: TObject);
begin
  if Assigned(self.OnAktualisieren) then
    self.OnAktualisieren(self.Daten);
end;


Und hier die Zuweisung in Form1:

ausblenden Delphi-Quelltext
1:
Einstellungen.Form2.OnAktualisieren := self.Aktualisieren;					


Wie gesagt soweit funktioniert alles. Nur habe ich die Zuweisung in Form1 noch auf einem Button liegen. Es sollte aber ja automatisch beim Start zugewiesen werden. Nur wenn ich das in Form1.OnCreate rein mache, geht das ja nicht, da zu dieser Zeit Form2 noch nicht existiert. Wenn ich die Erstellungsreihenfolge im Projekt rumdrehe (Form2 vor Form1) dann wird mir Form2 als "Hauptfenster" direkt angezeigt.
Also wo ist der beste Platz für die Zuweisung der Funktion aufs Event??

Gruß,
Jack

_________________
Es gibt keine dummen Fragen, nur dumme Antworten.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19322
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 07.01.14 21:13 
Naja, die Frage ist wo du das zweite Formular anzeigst. Am sinnvollsten dürfte sein es dort auch zu erstellen und zu initialisieren.

Und am besten gibst du dem Formular auch noch einen richtigen Namen... ;-)
jackle32 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 7

Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
BeitragVerfasst: Di 07.01.14 21:41 
Im Moment wird das Formular vom Projekt direkt erstellt und ich rufe nur Form2.Show in einem Button Event auf.

Ist es besser die Forms nur bei gebrauch zu erstellen und danach wieder zu zerstören?

Und ja das mit den Namen kommt noch wenn der Weg mal klar ist. :wink:

_________________
Es gibt keine dummen Fragen, nur dumme Antworten.