![]() |
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? |
AW: Frame laden und entladen
In der Code Lib ist ein Beispiel:
Komponenten die sich selbst freigeben. Du solltest es über die SuFu finden. |
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:
funktioniert nicht, Zugriffverletzung-Fehlermeldung.
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; Aber einfach
Delphi-Quellcode:
ging dagegen.
self.free;
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? |
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.
|
AW: Frame laden und entladen
Das war schon nicht ganz falsch, aber versuche mal nach dem
Delphi-Quellcode:
das hier:
self.free;
Delphi-Quellcode:
Gruß David
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; |
AW: Frame laden und entladen
OK, Ich habmich im Forum vertan,
hier der Link: ![]() Das mit dem Timer ist natürlich die einfachere Lösung |
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. |
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:
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:
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;
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:
Bei der Variante ist sicher, daß das Frame nicht mehr da ist.
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; 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. |
AW: Frame laden und entladen
Zitat:
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:
diesem Event eine Funktion aus Unit 3 zu, die beim Auslösen des Events gestartet wird?
Frame.OnDestroy = FrameDestroyed;
D.h. dadurch, dass dem Event in Unit 3 die Funktion aus Unit 3 zugewiesen wird, kann das Event diese Funktion starten (ohne Zugriffsverletzung)? |
AW: Frame laden und entladen
Kurz: Ja.
Lang: Zitat:
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:
Im Grunde kannst du dir das so vorstellen wie bei den Messages. Durch
Delphi-Quellcode:
(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:
Frame.OnDestroy := FrameDestroyed;
Delphi-Quellcode:
Ergo Events sind im Grunde nur die VCL-Kapselung von Messages.
if Sender is TMyFrame then
(Sender as TMyFrame).irgendwas_spezielles; // oder auch .Name oder .ComponentName wenn das reicht. Gruß David |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz