Delphi-PRAXiS

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/)
-   -   Delphi TListBox Objekte löschen (https://www.delphipraxis.net/141991-tlistbox-objekte-loeschen.html)

martin_ 20. Okt 2009 10:58


TListBox Objekte löschen
 
Hallo,
ich verwende zum Anzeigen die TListBox Komponente. Ein Objekt wird mit
Delphi-Quellcode:
 lst1.AddItem('String',cont);
zur Listbox (lst1) hinzugefügt. cont ist ein eigens Objekt der Klasse TObject. Meine Frage lautet gibt es bei einer ListBox so etwas wie OwnesObject bei einer TObjectList? Das Problem ist nämlich folgendes: Meiner Meinung erzeugt die Listbox für jedes hinzugefügte Objekt eine Kopie. Wird das ursprüngliche Objekt (cont) an einer anderen Stelle freigegeben, ist es in der Liste noch vorhanden. Nur kann ich es nicht auf der Liste abfragen welchen Zustand es hat (zb. wird das Objekt in der Liste nicht nil, obwohl es freigegeben wurde. Das Objekt selbst ist aber nil und kann dort auch so abgefragt werden).
Für das KeyPress Ereignis habe ich zb. folgenden Code für die Abfrage:
Delphi-Quellcode:
var
  obj : TObject;
begin
  if key = Char(VK_RETURN) then
  begin
    obj := lst1.Items.Objects[lst1.ItemIndex];

    if obj = nil then
    begin
      ShowMessage(' obj = nil');
    end;

    if obj is MyCont then
    begin
     ShowMessage(MyCont(obj).Value);
    end;

  end;
end;
Wobei das hinzugefügte Objekt für den Test so
Delphi-Quellcode:
  MyCont = class
    Value : string;
  end;
aussieht. Kurze Zusammenfassung: Objekt einer Listbox wird an einer anderen Stelle gelöscht, wie funktioniert die Abfrage?

mleyen 20. Okt 2009 11:05

Re: TListBox Objekte löschen
 
Hi,

Zitat:

Zitat von martin_
aussieht. Kurze Zusammenfassung: Objekt einer Listbox wird an einer anderen Stelle gelöscht, wie funktioniert die Abfrage?

soweit ich weiß, kannst du das nicht direkt Abfragen.
Das Problem hier ist einfach, das du mehrere Referenzen auf ein Objekt hast.
Diese Referenzen musst du alle 'nillen', um jedes prüfen zu können, ob es noch existiert.

Das einzige was du machen könntest wäre evtl auf eine andere Referenz zu prüfen, bei der sichergestellt ist, das sie genillt wurde.

Muetze1 20. Okt 2009 11:07

Re: TListBox Objekte löschen
 
Zitat:

Zitat von martin_
Das Problem ist nämlich folgendes: Meiner Meinung erzeugt die Listbox für jedes hinzugefügte Objekt eine Kopie. Wird das ursprüngliche Objekt (cont) an einer anderen Stelle freigegeben, ist es in der Liste noch vorhanden.

Tja, aber das ist wirklich auch nur deine Meinung. Delphi kann nicht einfach Objekte kopieren, hier gibt es keine Copy Constructoren wie bei C++. Das Objekt existiert nur einmal, die Instanzenvariablen wie cont sind nur Zeiger auf das eigentliche Objekt im Speicher. Beim Hinzufügen wird nur dieser Pointer in die Listbox eingetragen. Somit hast du 2 Pointer die auf den gleichen Speicher, ergo das gleiche Objekt zeigen. Das ist eine 1:n Beziehung. Wenn du nun das Objekt freigibst, z.B. mit .free, dann ist das Objekt im Speicher nicht mehr vorhanden, aber cont und Objects[] zeigen noch dahin wo es mal war. Wenn du nun mit FreeAndNil() arbeitest wird zumindest eine Stelle (cont) sogar noch auf einen definierten Wert gesetzt, aber der andere Pointer nicht.

Grundlegend ist dein Problem ein Designproblem. Du missachtest hier vor allem die Grundregel der Trennung von Code und Daten. Die Objekte müsstest du dir irgendwo unabhängig von der Darstellung halten. Damit ist immer gewährleistet wo du deine Informationen gesichert holen kannst, da der Ort gepflegt wird und die Referenz darstellt. Damit hast du eine zentrale und Oberflächen-unabhängige Stelle wo du Daten anlegst, veränderst und freigibst. Damit hast du dort auch die Möglichkeiten eine Aktualisierung der Oberfläche anzustoßen, etc. Wenn das der Fall ist, stellt sich deine Frage nicht mehr, da du niemals in der ListBox nachschauen brauchtest nach dem Objekt.

martin_ 20. Okt 2009 12:01

Re: TListBox Objekte löschen
 
Danke für die wirklich guten Antworten, die haben mir sehr genutzt.

Ich habe noch eine allgemeine Frage zu der Beziehung: auf ein Objekt zeigen zwei oder mehrere Pointer. Wie wird das Prinzipiell in anderen Sprachen allgemein gehandhabt. Gibt es dort Möglichkeiten herauszufinden ob/wann sich das Objekt verändert hat?

mleyen 20. Okt 2009 12:41

Re: TListBox Objekte löschen
 
Soweit ich weiß nicht, zumindest wär mir keine bekannt. (Wär ja auch irgendwo total overheaded, andauernd jede Referenz zu prüfen)

Ich weiß nur zu gut, dass es manchmal (gerade aus performancegründen) schnell und einfach geht mehrere Referenzen auf ein Objekt zeigen zu lassen. Nur wie Muetze1 schon sagt, ist das irgendwo nicht sauber.

[vorsicht, jetzt kommt was ganz abstruses]
Du könntest anstatt mit einer Referenz mit Referenzen auf eine Referenz zeigen, welche wiederum auf das Objekt zeigt.
Wo auch immer im Code du das Objekt jetzt freigibst, musst du nur die Referenz nillen, die auf das Objekt zeigt.
Überall anders kannst du jetzt über die Referenz, die auf die Objekt-Referenz zeigt, prüfen, ob das Objekt noch existiert. :mrgreen:
(Tipp am Rande: Sowas besser nur in eigenen Komponenten machen, die sich kein anderer anschaut. Das artet nur in Fragen aus :| )


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:41 Uhr.

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