Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - MainForm von einer Klasse aus benachrichtigen


LuMa86 - Mo 26.05.14 21:43
Titel: MainForm von einer Klasse aus benachrichtigen
Hallo,
Ich bin ja leider nur ein kleiner Hobby-Programmierer uns rätsel gerade an einer Frage: Wie kann ich aus meiner eigenen Klasse heraus, meine Main-Form benachrichtigen? Das heißt wenn etwas in meiner Klasse passiert, wird bei der MainForm ein Event ausgelöst, was dann etwas macht.

Aber irgendwie scheitert es bei mir schon am Konzept :/

Gruß


Moderiert von user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mo 26.05.2014 um 22:43


trm - Mo 26.05.14 22:07

Hallo.

Sobald Du im Code Deine Klasse auf Änderungen überprüfst, kannst Du in VCL mittels TMainForm auf Dein Hauptformular zugreifen.

Vielleicht hilft Dir ds schon ein wenig weiter.


LuMa86 - Mo 26.05.14 23:23

Hat geholfen wie ein Schlag auf den Hinterkopf :D Manachmal brauche ich einfach jemanden der mich mit dem Kopf druafstößt :)

Danke !


Xion - Di 27.05.14 08:11

Allgemein macht man sowas über Events, das ist flexibler als auf eine MainForm zuzugreifen, die sich dann später auch mal ändern könnte (oder hab ich den Hinweis nicht richtig verstanden?).

Das ganze sieht dann in etwa so aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
type TSomethingChangedEvent = procedure(newValue: integer) of object;
type TMyClass = class
  private
    vValue: integer;
    vOnSomethingChanged: TSomethingChangedEvent;
  public
    procedure DoSomething(x: integer);
    property OnSomethingChanged: TSomethingChangedEvent read vOnSomethingChanged write vOnSomethingChanged;
end;

procedure TMyClass.DoSomething(x: integer);
begin
  if x mod 2 <> vValue mod 2 then
    if Assigned(vOnSomethingChanged) then
      OnSomethingChanged(x mod 2);
  vValue := x;
end;


In der Main Klasse:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TMainForm.ChangedHandler(newValue: integer);
begin
  if newValue mod 2 = 0 then
    ShowMessage('even value stored')
  else
    ShowMessage('odd value stored');
end;

procedure TMainForm.Create;
var MyClass: TMyClass;
begin
  MyClass := TMyClass.Create;
  MyClass.OnSomethingChanged := ChangedHandler;
  MyClass.DoSomething(20);
  MyClass.DoSomething(23);
  MyClass.DoSomething(25);
  MyClass.DoSomething(30);
  MyClass.Free;
end;


WasWeißDennIch - Di 27.05.14 08:11

Wieso denn ein Event des Formulars statt der Klasse? Oder hab ich das falsch verstanden?


Xion - Di 27.05.14 08:11

Mist, Doppelpost...die Knöpfe sind aber auch irgendwie schwer auseinander zu halten...also muss ich noch was konstruktives sagen...hmmm :oops:

Eine andere Möglichkeit wäre das Verknüpfen der Form mit der Klasse, ist aber typischerweise nicht so flexibel:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
type TMyClass = class
  private
    vOwner: TForm;
  public
    constructor Create(Owner: TForm);
    procedure DoSomething(x: integer);
end;

constructor TMyClass.Create(Owner: TForm);
begin
  vForm := Owner;
end;    

procedure TMyClass.DoSomething(x: integer);
begin
  vForm.Caption := 'hello world';
end;


LuMa86 - So 01.06.14 18:38

Um euch zu beruhigen: WasWeißIchDenn's erster Post hat mich auf die Idee gebracht es mit Events zu machen. Ich weiß zwar nicht wie ich von selbst auf einmal darauf gekommen bin aber ich mache ziemlich genau so wie du in deinem ersten Post Xion :)

Danke für den Denkanstoß :)


Delete - So 01.06.14 23:49

Wenn sich deine Klasse standardmäßig in einer eigenen Unit befindet, müßtest du von dieser Unit aus deine Mainform-Unit referenzieren (= in deiner Klasse unter Uses die Haupt-Unit eintragen). Das kann problematisch werden, denn deine Mainform-Unit referenziert vermutlich bereits deine Klassen-Unit. Natürlich könntest du die Referenzierungen (Uses) jeweils unter Implementation vornehmen, so daß die beiden Klassen nichts von den Implementation-Referenzierungen der jeweils anderen "wissen". Doch auch das kann u.U. problematisch werden.

Deshalb ist es eleganter und programmtechnisch variabler, wenn du für solche Fälle ein Ereignis deklarierst, wie oben von Xion sehr schön gezeigt wurde. In deinem Mainform-Code weist du dem Ereignis dann nur noch den richtigen Event-Handler zu: Eine Methode deiner Mainform-Klasse, die das tut, was im Falle des Ereignisses getan werden soll.

Das Schöne an der Sache ist, daß einerseits auch andere Formulare diesem Ereignis einen Eventhandler zuweisen können und andererseits dieses Ereignis in deiner Klasse mehrfach verwendet werden kann: Ich hab z.B. ein Ereignis im Datenmodul, das in der Mainform diverse Statusanzeigen aktualisieren soll, und zwar bei diversen Aktionen, die im Datenmodul geschehen: AfterPost, AfterScroll und was weiß ich noch können in ihren Eventhandlern immer dasselbe Ereignis zur Aktualisierung der Statusanzeigen im Hauptformular auslösen. Das vereinfacht die Sache ungemein.

Früher hab ich das auch so gemacht mit dem gegenseitigen Referenzieren. Doch seit ich diese Event-Geschichte kenne und anzuwenden weiß, bin ich davon begeistert und mache das nur noch auf diese Weise.


ZeitGeist87 - Mo 02.06.14 15:48

Events sind die beste Lösung.

[OT]
Dazu fällt mir ein vor einigen Wochen gemachtes SVN-Commit wieder ein.
Meine Azubis dachten, sie seinen total clever:


Quelltext
1:
2:
3:
@Private und Marshall<Name der Redaktion geändert>: Wenn ich noch EINMAL, EIN EINZIGES MAL den Aufruf von Formularen in Klassen sehe, gibt´s Ärger!
Klassen haben keinerlei Zugriff auf irgendwelche Formulare. Ihr habt alles so aufzubauen, dass die Klasse die Logik übernimmt und wenn die passt, ein Formular eine Interaktion ausführt!
Bei Gelegenheit gehe ich den kompletten Code in CArma durch und entferne alles, was mir nicht passt. Fehler dürft ihr dann suchen.


Nersgatt - Mi 04.06.14 15:33

user profile iconZeitGeist87 hat folgendes geschrieben Zum zitierten Posting springen:
Events sind die beste Lösung.

[OT]
Dazu fällt mir ein vor einigen Wochen gemachtes SVN-Commit wieder ein.
Meine Azubis dachten, sie seinen total clever:

Lol! na hoffentlich hast Du den Azubis schon beigebracht, wie sie sich die Unterschiede der Revisionen anschauen. Damit sie auch die Stellen finden, die Dir nicht passen. :D