![]() |
Events und SpeicherLeaks bei dynamischen Buttons
Meine Fragestellung:
Es gibt eine Form1. Diese enthält drei Buttons, ShowForm2 und ShowForm3 und Close. Es gibt eine Form2. Diese enthält zwei zur Laufzeit mittels TButtonNames erzeugt Buttons Close und ShowForm3. Es gibt eine Form3. Diese enthält einen zur Laufzeit mittels TButtonNames erzeugten Button Close. In der Projekt.dpr wird zum Schluss nach Speicherlöchern abgefragt, mit: ReportMemoryLeaksOnShutdown := true; Es gibt eine Klasse TButtonNames .
Delphi-Quellcode:
Das Event:type TButtonNames = class public procedure LinkProcedure1(linkedProcedure: TLinkedProcedure); function ButtonsForForm2(anzahlButton: integer): TArrayOfTBitBtn; function ButtonsForForm3(anzahlButton: integer): TArrayOfTBitBtn; destructor destroy; override; end; implementation var handlerKlickEvent: THandlerLinkedProcedure; destructor TButtonNames.destroy; begin FreeAndNil(handlerKlickEvent); for i := 0 to High(fbuttons) do FreeAndNil(fbuttons[i]); inherited; end; procedure TButtonNames.LinkProcedure1(linkedProcedure: TLinkedProcedure); begin handlerKlickEvent := THandlerLinkedProcedure.Create; handlerKlickEvent.OnKlick := linkedProcedure; end; function TButtonNames.ButtonsForForm2(anzahlButton: integer): TArrayOfTBitBtn; begin for i := 0 to anzahlButton - 1 do begin fbuttons[i] := TBitBtn.Create(form); fbuttons[i].OnClick := handlerKlickEvent.GetKlick; end; end; function TButtonNames.ButtonsForForm3(anzahlButton: integer): TArrayOfTBitBtn; begin for i := 0 to anzahlButton - 1 do begin fbuttons[i] := TBitBtn.Create(form); fbuttons[i].OnClick := handlerKlickEvent.GetKlick; end; end;
Delphi-Quellcode:
Form2 und Form3 erzeugen bei Aufruf die Buttons.
TLinkedProcedure = procedure(sender: TObject) of object;
THandlerLinkedProcedure = class private fLinkedProcedure: TLinkedProcedure; public property OnKlick: TLinkedProcedure read fLinkedProcedure write fLinkedProcedure; procedure GetKlick(sender: TObject); end; In Form2:
Delphi-Quellcode:
in Form3:
Buttons := TButtonNames.Create;
Buttons.LinkProcedure1(EmpfangeKlick); Buttons.ButtonsForForm2(2); // oder NamesForForm3(1);
Delphi-Quellcode:
beide haben LinkProcedure1(EmpfangeKlick);
Buttons := TButtonNames.Create;
Buttons.LinkProcedure1(EmpfangeKlick); Buttons.ButtonsForForm3(1); EmpfangeKlick sind Prozeduren in Form2 und Form3:
Delphi-Quellcode:
Wenn jetzt in Form1 auf Button ShowForm3 geklickt wird, erscheint Form3 mit allen erzeugten Buttons, Nämlich der Button „Close“.
procedure Form2.EmpfangeKlick(Sender: TObject);
begin if (Sender = fbuttons[0]) then Close; if (Sender = fbuttons[1]) then ShowForm3; end; Form3 wird durch klick auf „Close“ geschlossen. Form1 mit Klick auf Close geschlossen – Keine SpeicherLeaks werden angezeigt. Wenn in Form1 auf ShowForm2 geklickt wird, erscheint Form2 mit allen erzeugten Buttons. Nämlich ShowForm3 und Close. Form2 schließen mit Close. Form1 schließen. - Keine SpeicherLeaks werden angezeigt. Bei Klick in Form2 auf ShowForm3 wird Form3 angezeigt mit dem Close Button. Schließen Form3 mit Close, gehts zurück zu Form2. Form2 schließen mit Close. Form1 schließen und SpeicherLeaks werden angezeigt. Wenn in TButtonNames eine zweite Variable
Delphi-Quellcode:
erzeugt wird, und eine zweite Prozedure
handlerKlickEvent2: THandlerLinkedProcedure;
Delphi-Quellcode:
und aufruf in Form3:
procedure TButtonNames.LinkProcedure2(EmpfangeKlick);
begin handlerKlickEvent2 := THandlerLinkedProcedure.Create; handlerKlickEvent2.OnKlick := linkedProcedure; end;
Delphi-Quellcode:
Dann werden niemals SpeicherLeaks angezeigt.
Buttons := TButtonNames.Create;
Buttons.LinkProcedure2(EmpfangeKlick); Buttons.ButtonsForForm3(1); Warum muß ich eine zweite Variable und eine zweite procedure in TErzeugeButtons erstellen? Oder, was was hab ich falsch gemacht? Danke im voraus. |
AW: Events und SpeicherLeaks bei dynamischen Buttons
Hi,
wäre interessant zu wissen wo Speicherleaks angezeigt werden. Das Problem liegt meiner Meinung nach daran, dass du nur eine Variable hast:
Delphi-Quellcode:
.
var handlerKlickEvent: THandlerLinkedProcedure;
Die Referenz wird bei
Delphi-Quellcode:
einfach überschrieben wenn du es 2 mal aufrufst und kannst du sie nicht mehr freigeben.
procedure TButtonNames.LinkProcedure1(linkedProcedure: TLinkedProcedure);
begin handlerKlickEvent := THandlerLinkedProcedure.Create; handlerKlickEvent.OnKlick := linkedProcedure; end; |
AW: Events und SpeicherLeaks bei dynamischen Buttons
Hallo,
der Quellcode kommt mir etwas seltsam vor
Delphi-Quellcode:
Ohne es ausprobiert zu haben, fehlt hier nicht ein (zwei) End;
function TButtonNames.ButtonsForForm2(anzahlButton: integer): TArrayOfTBitBtn;
begin for i := 0 to anzahlButton - 1 do begin fbuttons[i] := TBitBtn.Create(form); fbuttons[i].OnClick := handlerKlickEvent.GetKlick; end; function TButtonNames.ButtonsForForm3(anzahlButton: integer): TArrayOfTBitBtn; begin for i := 0 to anzahlButton - 1 do begin fbuttons[i] := TBitBtn.Create(form); fbuttons[i].OnClick := handlerKlickEvent.GetKlick; end; mfg frank |
AW: Events und SpeicherLeaks bei dynamischen Buttons
@CarlAshnikov
SpeicherLeaks werden beim schließen des Programms angezeigt. Es werden zwei verschiedene Objekte von TButtonNames erzeugt. Einmal in Form2 und einmal in Form3. Jede Form hat ihre eigenen Buttons. Die Button von Form3 sollten also die von Form2 nicht kennen. D.h. Button von Form3 haben ihre eigene LinkProcedure1 und die von Form2 ebenfalls ihre eigene LinkProcedure1 und dazu ihre eigene handlerKlickEvent Variable. Sonst wäre das doch so, als wenn ich zwei Objekte vom Typ TAuto erstelle und die teilen sich ein Rad. wenn ich
Delphi-Quellcode:
mache.
implementation
var rad1,rad2,rad3,rad4 : TRad Oder? |
AW: Events und SpeicherLeaks bei dynamischen Buttons
Doch genau das tun sie, wenn du es so definierst. Wenn etwas nur zu einem Objekt gehören soll dann muss du das als Feld des Objektes definieren:
Delphi-Quellcode:
Ist in diesem Fall aber egal weil du bei jedem Aufruf der
TAuto = class
private fRad1, fRad2, fRad3, fRad4: TRad; public procedure Fahren; end;
Delphi-Quellcode:
immer wieder über deine Referenz drüberbügelst. Dass du die Variablen unterhalb von
procedure TButtonNames.LinkProcedure1(linkedProcedure: TLinkedProcedure);
Delphi-Quellcode:
definierst sorgt nur dafür, dass außerhalb der Unit keiner darauf zugreifen kann.
implementation
Kleiner Test gefällig?
Delphi-Quellcode:
TTest = class public procedure Test; end; TForm2 = class(TForm) procedure FormCreate(Sender: TObject); end; implementation var globalObj: TObject; procedure TForm2.FormCreate(Sender: TObject); var vT1, vT2: TTest; begin vT1 := TTest.Create; vT2 := TTest.Create; vT1.Test; vT2.Test; end; { TTest } procedure TTest.Test; begin if assigned(globalObj) then raise Exception.Create('Oha') else globalObj := TObject.Create; end; |
AW: Events und SpeicherLeaks bei dynamischen Buttons
Zitat:
Und wo wird die Größe des Arrays gesetzt? Ich sehe nirgends ein SetLength? |
AW: Events und SpeicherLeaks bei dynamischen Buttons
Ah, natürlich.
Alles klar jetzt. Der
Delphi-Quellcode:
muß zu den Objekt vars.
handlerKlickEvent: THandlerLinkedProcedure;
Vielen danke für die Erleuchtung. Gruß |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:45 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 by Thomas Breitkreuz