Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Frame laden und entladen (https://www.delphipraxis.net/158351-frame-laden-und-entladen.html)

Jumpy 14. Feb 2011 15:21

Frame laden und entladen
 
Für ein Übungsprojekt, soll ich ein dynamisch generiertes Form erstellen. Dies geschieht, indem vorgefertigte Frames in das Formular geladen und auf Panels platziert werden.
Das klappt soweit schon ganz gut.

Jetzt sollen aber manche Frames (wenn dort was passiert ist) selber den Befehl geben können, sich wieder zu entladen. Vereinfacht: Angenommen auf dem Frame ist auch ein Button. Bei klicken auf diesen, soll der Frame gelöscht werden und das Formular neu angezeigt (oder neu aufgebaut?) werden.

Wie geh ich da vor? Der Frame gehört ja dem Formular und dieses bestimmt, ob und wann ein Frame gelöscht wird, oder? D.h. ich muss vom Frame Nachricht an das Form geben?

WM_CLOSE 14. Feb 2011 15:40

AW: Frame laden und entladen
 
In der Code Lib ist ein Beispiel:
Komponenten die sich selbst freigeben.
Du solltest es über die SuFu finden.

Jumpy 14. Feb 2011 15:53

AW: Frame laden und entladen
 
Ich such mal, hab bisher aber noch nicht die rechte Suchwort-Kombi gefunden
(Freigeben, Free, Komponente, selbst, sich), da ich wahrsch. die Begrifflichkeiten nicht 100% klar habe.

Meanwhile:
Delphi-Quellcode:
for i := 0 to TComponent(self.Owner).ComponentCount -1 do
    if TComponent(self.Owner).Components[i].Name = self.Name then
      TComponent(self.Owner).Components[i].Free;
funktioniert nicht, Zugriffverletzung-Fehlermeldung.

Aber einfach
Delphi-Quellcode:
self.free;
ging dagegen.

D.h. so krieg ich das Frame gelöscht und die darunter liegenden Frames rücken eins auf (stehen alle auf Alignment := alTop). Allerdings bleibt dann unten eine Fläsche des Panels (auf dem der Frame lag) leer, d.h. die Panel-Höhe müsste neu berechnet werden und spätestens das muss doch eine Funktion auf Form-Ebene machen, oder? Wie stoß ich die an ohne Zugriffsverletzung?

stahli 14. Feb 2011 16:26

AW: Frame laden und entladen
 
Du könntest den Frame einfach "markieren" (am einfachsten mit Frame.Tag := 1) und über einen Timer alle Frames auf die Markierung prüfen und ggf. löschen.

David Martens 14. Feb 2011 16:42

AW: Frame laden und entladen
 
Das war schon nicht ganz falsch, aber versuche mal nach dem
Delphi-Quellcode:
self.free;
das hier:

Delphi-Quellcode:
for i := 0 to TComponent(self.Owner).ComponentCount -1 do
    if TComponent(self.Owner).Components[i] is TYourFrame then
      TYourFrame(TComponent(self.Owner).Components[i]).Repaint;
Gruß David

WM_CLOSE 14. Feb 2011 17:32

AW: Frame laden und entladen
 
OK, Ich habmich im Forum vertan,
hier der Link: http://www.delphi-treff.de/tipps/obj...igeben-lassen/

Das mit dem Timer ist natürlich die einfachere Lösung

Jumpy 15. Feb 2011 10:08

AW: Frame laden und entladen
 
Ich hab es erstmal einfach mit der Timer-Lösung gemacht.
Die komponente, die gelöscht werden will, setzt ihren Tag auf den Wert ihrer Höhe.
In der übergeordneten Komponente werden im OnTimer-Event alle die Tags aller Untergeordneten Komponenten untersucht. Ist einer <> 0, so wird a) die Komponente gelöscht und b) die Höhe der übergeordneten Komponente um den Wert in Tag verindert.

Ist zwar alles nicht elegant, aber es funktioniert.

OT:
Hab den Eindruck, dass man, wenn man manche Sachen so kompliziert (im Sinne von über Umwege) löst, man wahrscheinlich von Anfang an einen Design-Fehler drin hat und das es mit einer anderen Struktur vllt. einfacher wäre. Umgekehrt lernt man aber wahrsch. nur über so Krücken und mit der Zeit (und Hilfe in Foren, wie hier:thumb: ) wie man es besser macht. Zwar gibt es Bücher über so Dinge wie Design-Patterns usw. (die ich sicher irgendwann mal lesen werde) aber diese oft Abstrakten Konzepte dann auf sein konkretes Problem zu modelieren ist dann nur mit Erfahrung möglich.
Ist ja mit der OOP ähnlich. Da haste in der Schule schicke Beispiele von Autos oder Tieren im Zoo, wo das alles eigentlich ganz logisch klingt, aber bei einem realistisches Problem bei der Arbeit zu überlegen, wie pack ich das in Klassen usw. ist schon was anderes.

David Martens 15. Feb 2011 10:56

AW: Frame laden und entladen
 
Jetzt verstehe ich was du willst.

Hier wie ich es machen würde:
Delphi-Quellcode:
unit1
  TMyFrame = class(TFrame)
    FOnDestroy : NotifyEvent;
  property
    OnDestroy : NotifyEvent read FOnDestroy write FOnDestroy;
  end;
Delphi-Quellcode:
unit2

uses
  unit1;

type
  TShowFrame = class(TMyFrame)
    destructor Destroy; override;
  end;

destructor TShowFrame.Destroy;
begin
  if Assigned(OnDestroy) then
    OnDestroy(Self);

  inherited;
end;
Delphi-Quellcode:
unit3

uses
  unit1, unit2;

type
  TShowForm = class(TForm)  
    procedure FrameDestroyed(Sender : TObject);
  end;

procedure TShowForm.FrameErzeugen;
begin
  // Frame vom Typ TShowFrame erstellen und
  Frame.OnDestroy = FrameDestroyed;
end;

procedure TShowForm.FrameDestroyed(Sender : TObject);
begin
  // neu zeichnen der anderen Frames
end;
In FrameDestroyed ist das sendende Frame allerdings noch da. Darauf muß man dann achten. wenn dem nicht so sein soll, dann muß man mit SendMessage arbeiten:

Delphi-Quellcode:
unit1
const
  MY_MESSAGE = WM_USER + 1; // alles über WM_USER geht
Delphi-Quellcode:
unit2

uses
  unit1;

type
  TShowFrame = class(TMyFrame)
    destructor Destroy; override;
  end;

destructor TShowFrame.Destroy;
begin
  SendMessage(Self.Handle, MY_MESSAGE, 0, 0);

  inherited;
end;
Delphi-Quellcode:
unit3

uses
  unit1, unit2;

type
  TShowForm = class(TForm)  
    procedure FrameDestroyed(var msg: TMessage); message MY_MESSAGE;
  end;

procedure TShowForm.FrameDestroyed(var msg: TMessage);
begin
  // neu zeichnen der Frames
end;
Bei der Variante ist sicher, daß das Frame nicht mehr da ist.

P.S.: Es kann der eine oder andere kleine Fehler drin sein, ich wollte nur die Konzepte erläutern.

Gruß David

PPS.:
@Jumpy

not so OT: Programmieren besteht zu über 50% aus Design und dann erst Entwicklung. Man muß sich im Großen wie im Kleinen über für ein Konzept entscheiden. Das hängt davon ab was man machen will, was der Kunde will, wie das Problem umgesetzt werden kann und viele andere Faktoren.
Es gibt da einen Spruch. Jede Minute die du am Konzept verlierst gewinnst du beim Entwickeln. Soll heißen wenn das Kontept vollständig ist (was es wohl nie sein wird) kann es beim eigentlichen Schreiben des Codes keine Überaschungen mehr geben.

Jumpy 15. Feb 2011 11:52

AW: Frame laden und entladen
 
Zitat:

Zitat von David Martens (Beitrag 1081790)
Jede Minute die du am Konzept verlierst gewinnst du beim Entwickeln.

Das kenn ich schon aus der Datenbankentwicklung, wo man sich auch erstmal ordentlich Gedanken machen muss. Nur das da die Strukturen mMn weniger komplex sind, d.h. eine DB ist recht schnell bis zur bzw, in der Xten Normalform geplant. Beim Programmieren sind die Konzepte vielfältiger, gibt es mehr zu bedenken. (Hab bisher aber nur mit relationalen-DBs mit vllt. max. 30 Tabellen gearbeitet).

BTTT(back to the topic):
Danke für dein Beispiel. Ich hab es auch fast verstanden :)
Hast du in der Unit1 für MyFrame ein neues, eigenes Event angelegt? Macht man das so? Hab das noch nie gemacht, darum die Neugier.
Weißt du in Unit 3 mit
Delphi-Quellcode:
Frame.OnDestroy = FrameDestroyed;
diesem Event eine Funktion aus Unit 3 zu, die beim Auslösen des Events gestartet wird?
D.h. dadurch, dass dem Event in Unit 3 die Funktion aus Unit 3 zugewiesen wird, kann das Event diese Funktion starten (ohne Zugriffsverletzung)?

David Martens 15. Feb 2011 12:34

AW: Frame laden und entladen
 
Kurz: Ja.

Lang:
Zitat:

Hast du in der Unit1 für MyFrame ein neues, eigenes Event angelegt?
Genau, In unit1 habe ich ein eigenes Event angelegt.
Das kannst du auch selbst sehen, wenn du dich mal die Klassen "herunterhangelst" <strg> und click auf die Grundklasse eine Komponente z.B: TButton, da stehen dann irgendwann ganz viele solcher Events.

2.
Zitat:

Weißt du in Unit 3 diesem Event eine Funktion aus Unit 3 zu
nicht ganz.
Im Grunde kannst du dir das so vorstellen wie bei den Messages.
Durch
Delphi-Quellcode:
Frame.OnDestroy := FrameDestroyed;
(sorry Fehler mit ":") wird dem Frame gesagt welche Prozedur aufgerufen/ausgelöst werden soll, wenn dieser Event auftritt. FrameDestroyed läuft immernoch in der Form. Damit man in der Form aber auf verschiedene Events reagieren kann ist ein Sender vorhanden. Da kann man dann den richtigen Sender herausfinden:
Delphi-Quellcode:
if Sender is TMyFrame then
  (Sender as TMyFrame).irgendwas_spezielles; // oder auch .Name oder .ComponentName wenn das reicht.
Ergo Events sind im Grunde nur die VCL-Kapselung von Messages.

Gruß David


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:30 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz