Autor |
Beitrag |
jackle32
      
Beiträge: 183
Erhaltene Danke: 7
Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
|
Verfasst: 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
      
Beiträge: 19322
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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
      
Beiträge: 96
Erhaltene Danke: 24
Delphi 2010, C# (VS 2012), Objective-C, Java
|
Verfasst: 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
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 07.01.14 12:36
vagtler hat folgendes geschrieben : | Grundsätzlich ist das wohl ein Fall für den Einsatz einer Fassade. | Hihi.
@ jaenicke: das will jackle32 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 
_________________ "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
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: 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
      
Beiträge: 19322
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 07.01.14 14:09
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 07.01.14 16:11
jaenicke hat folgendes geschrieben : | Das hast du falsch verstanden. |
Oh, stimmt, da hat er mich mit den vielsagenden Unit- und Formnamen verwirrt
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 
      
Beiträge: 183
Erhaltene Danke: 7
Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
|
Verfasst: 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:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm2.BtnSpeichernClick(Sender: TObject); begin Form1.Aktualisieren; end; |
Mir ist nur leider kein Ausweg eingefallen.
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:
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:
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
      
Beiträge: 19322
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 183
Erhaltene Danke: 7
Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
|
Verfasst: 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. 
_________________ Es gibt keine dummen Fragen, nur dumme Antworten.
|
|
|