![]() |
Arbeiten mit Tobjectlist
Hallo,
ich arbeite mit verschiedenen Objecten, die die Klasse TObjectlist beinhalten:
Delphi-Quellcode:
Nun habe ich ein Project deklariert und auch "kreirt"
Tseite=class
save: Tsave; pic: Timage; objects: TObjectlist; end; Tproject=class save: Tsave; Pages: Tobjectlist; end;
Delphi-Quellcode:
Nun werden im Nachfolgenden Immer Objecte der Klasse Tseite project.pages zugefügt:
var project: Tproject;
begin project:=Tproject.Create project.pages:=Tobjectlist.Create
Delphi-Quellcode:
Und jetzt zu dem Problem, ich kann nicht auf "project.pages.Items[index].save" zugreifen..
project.pages.add(TSeite.Create);
Wo liegt bei dieser Verschachtelung das Problem und wie löse ich es? Interessant ist das ganze, da es später zu weiteren Verschachtelungen in der Klasse Tseite kommt und so weiter kommt. mfg KahPee Edit: Kann ich eigentlich festlegen, dass in die Objectliste (project.pages) nur Objecte des Types Tseite geladen werden können? |
Re: Arbeiten mit Tobjectlist
du musst die einzelnen items in der objectlist casten:
Delphi-Quellcode:
Oder von welchem typ auch immer deine Objekte in der List sind
tSeite(project.pages.items[0]).save;
|
Re: Arbeiten mit Tobjectlist
Wenn du das Item wieder aus der Objektliste holst, musst du es erst wieder in das jeweilige Objekt casten.
Delphi-Quellcode:
Tseite(project.pages.Items[index]).save
|
Re: Arbeiten mit Tobjectlist
Delphi-Quellcode:
würde das Funktionieren (vorrausgesetzte Tsave enthält den Boolean save)?
tSeite(project.pages.items[0]).save.saved:=true;
Kann ich also die ObjeKte der Liste so direkt bearbeiten? Noch eine Frage zu weiteren Verschachtelungen; ginge das dann auch so:
Delphi-Quellcode:
mfg Kahpee
//weitere Deklaration
Tfigure=class(Tobject) public pos: Tpoint end; {zugriff auf das Object welches in der Objectliste einer Klasse des Typs Tseite (welche wiederum in der Liste der Klasse Tproject) deklariert ist} Tfigure(Tseite(project.pages.Items[index]).objects.items[index]).pos |
Re: Arbeiten mit Tobjectlist
Wird eigentlich Tseite(project.pages.last).pic freigegeben wenn:
Delphi-Quellcode:
bzw. was für einen Owner muss ich beim Konstruieren des Image angeben um genau das zu erreichen?
Tseite(project.pages.last).delete;
//oder project.pages.free Tseite(project.pages.last) funktioniert als Owner nicht, da Tseite mit Tcomponent inkompatibel ist. |
Re: Arbeiten mit Tobjectlist
Da diese untergeordneten Objekte zum Objekt gehören, sollten (gemäß den OOP-Regeln) diese auch nur von diesem Objekt erzeugt und freigegeben werden.
> Constructor und Destructor Wenn du dir eine neues Objekt von TObjectList ableitest und das Property Items neu deklarierst, dann kannst du diesem direkt den Typ Tseite, bzw. Tfigure verpassen und ersparst dir dann so die Typumwandlungen. |
Re: Arbeiten mit Tobjectlist
Zitat:
WIe genau meinst du das mit dem ableiten. Ich mache das shcon an anderer Stelle, aber wie wäre in diesem Fall um sich die Arbeit zu vereinfachen? Könntest du mir da ein Beispiel geben? |
Re: Arbeiten mit Tobjectlist
Zitat:
damit diese tseite zurück gibt und nicht tobject. |
Re: Arbeiten mit Tobjectlist
wie würde das denn jetzt so als Beispiel aussehen? Ich progge erst seit kurzem mit Klassen, daher komm ich da nicht von alleine drauf :(
|
Re: Arbeiten mit Tobjectlist
So zum beispiel:
TMeinObject kann zB dein TSeite sein
Delphi-Quellcode:
type
TMyList = class(TObjectList) public function Add(AObject: TMeinObject): Integer; function First: TMeinObject; function Last: TMeinObject; property Items[Index: Integer]: TMeinObject read GetItem write SetItem; default; end; |
Re: Arbeiten mit Tobjectlist
mh.. das hat leider bei mir keine Glühbirne aufleuchten lassen :(
Was genau machen die einzelnen Zeilen? Die ändern doch eigentlich nichts außer, dass es jetzt nicht mehr jedes beliebige Objekt sein kann, welches in der Liste gespeichert werden kann, sondern nur noch objekte des typs Tseite. Gibt mir das die Möglichkeit so auf die Objekte der Liste zuzugreifen wie ich das vorhatte? project.pages.Items[index].save.... Das übernehmen deines Beispiels gibt auf jeden Fall erstmal nur Fehler. Ich hab auch keine Ahnung (:() wie ich die einzelnen Prozeduren deklarieren soll, die in TSeiteList deklariert werden...
Delphi-Quellcode:
Ansonsten nochmal zu der Frage mit den Konstruktoren. Was passiert mit
TseiteList = class(TObjectList)
public function Add(AObject: TSeite): Integer; function First: TSeite; function Last: TSeite; property Items[Index: Integer]: TSeite read GetItem write SetItem; default; end;
Delphi-Quellcode:
wenn ich das hier ausführe:
Tseite(project.pages.last).pic:=Timage.create(self)
Delphi-Quellcode:
Tseite(project.pages.last).delete;
|
Re: Arbeiten mit Tobjectlist
Ja, so kannst du machen was du machen möchtest.
So ersparst du dir das ganze rumcasten außerhalb der Objectliste. So würden die implementierungen sein:
Delphi-Quellcode:
{ TMyList }
function TMyList.Add(AObject: TMeinObject): Integer; begin result:=inherited Add(AObject); end; function TMyList.First: TMeinObject; begin result:=TMeinObject(Inherited First); end; function TMyList.GetItem(Index: Integer): TMeinObject; begin result:=TMeinObject(inherited items[index]); end; function TMyList.Last: TMeinObject; begin result:=TMeinObject(inherited Last); end; procedure TMyList.SetItem(Index: Integer; const Value: TMeinObject); begin inherited Items[index]:=Value; end; |
Re: Arbeiten mit Tobjectlist
Vielen Dank, auf den ersten Blick leuchten mir einige Dinge ein. Angepasst hab ich das mal ins projekt gepackt und leider gibt es recht viele Fehlermeldungen (stehen als kommentare dabei):
Delphi-Quellcode:
TseiteList = class(TObjectList)
public function Add(AObject: TSeite): Integer; function First: TSeite; function Last: TSeite; property Items[Index: Integer]: TSeite read GetItem write SetItem; default; //fehler mit inkompatiblen typen end; function TseiteList.Add(AObject: TSeite): Integer; begin result:=inherited Add(AObject); end; function TseiteList.First: TSeite; begin result:=TSeite(Inherited First); end; function TseiteList.GetItem(Index: Integer): TSeite; //Fehler: undefinierter bezeichner begin result:=TSeite (inherited items[index]); //Result undefiniert (bei ner Funktion, was will der den da?????) //Fehler: Diese Form des Methodenaufrufs ist nur in Methoden von abgeleiteten Typen erlaubt //[Pascal Fehler]: 'ENDE' erwartet, aber ')' gefunden end; function TseiteList.Last: TSeite; begin result:=TSeite(inherited Last); end; procedure TseiteList.SetItem(Index: Integer; const Value: TSeite); //undef. bezeichner Setitem begin inherited Items[index]:=Value;{ [Pascal Fehler] : '=' erwartet, aber ')' gefunden [Pascal Fehler] : Diese Form des Methodenaufrufs ist nur in Methoden von abgeleiteten Typen erlaubt} end; |
Re: Arbeiten mit Tobjectlist
Delphi-Quellcode:
Die Methoden fehlen natürlich noch in der deklaration der klasse. Dann funktioniert es.
type
TSeiteListe=Class(TObjectList) private function GetItem(Index: Integer): TSeite; procedure SetItem(Index:integer;Value:TSeite); public .... end; |
Re: Arbeiten mit Tobjectlist
Wie sehen dann denn die neuen Aufrufe auf?
Delphi-Quellcode:
project.Pages.Add(Tseite.create); // so noch richtig?
project.Pages.Items[pages.last].pic:=TImage.create; //[Pascal Fehler] Inkompatible Typen: 'Integer' und 'Tseite' //bezieht sich auf das "Items[pages.last]" Die Prozeduren Last und Fist müssten doch eig. einen Integer als ergebnis haben oder?!
Delphi-Quellcode:
function TseiteList.Last: Integer; //Deklaration in der Klasse ebenfalls angepasst
begin result:=TSeite(inherited Last); //<-- hier besteht weiterhin die Inkompabilität zwischen Tseite und Integer end; |
Re: Arbeiten mit Tobjectlist
Man kann aber keine Integer nach TSeite casten
|
Re: Arbeiten mit Tobjectlist
DAs erschließt sich ja aus der Fehlermeldung. Die Frage ist wie man das Problem löst. Das muss ja schon irgendwie gehen ;)
|
Re: Arbeiten mit Tobjectlist
Lass den Cast einfach weg. :zwinker:
|
Re: Arbeiten mit Tobjectlist
du meinst ich brauch "function TseiteList.Last: Integer; " gar nicht neu zu definieren?
|
Re: Arbeiten mit Tobjectlist
Eigentlich nicht
|
Re: Arbeiten mit Tobjectlist
Ehm ja.. das war dämlich.. Die Deklarationen von daywalker waren völlig richtig. PAges.last gibt selbstverständlich ein Objekt des Typs Tseite aus und nicht den Integer des letzten Objekts.. das war ein Denkfehler meinerseits.
Wenn ich das richtig verstanden habe muss ich jetzt noch die anderen Funktionen (Delete, move, etc.) sodenn ich sie brauche anpassen. Vorweg jetzt aber noch einmal die Frage zu den Ownern, damit ich keine Speicherlöcher produziere: Pages.Last.pic:=TImage.create; Wird diese Image nun bei Pages.last.delete wieder freigegeben? Oder muss ich das manuell machen? |
Re: Arbeiten mit Tobjectlist
Ja, der Eigentümer gibt seinen "Besitz" bei seinem "Tod" frei
Alternative wäre, wie Frank schon erwähnt hat, eine generische Liste zu verwenden. Dafür wäre aber D2009 notwendig |
Re: Arbeiten mit Tobjectlist
Heißt das, dass bei Klassen immer alles untergeordneten Klassen mit freigegeben werden, wenn die Klasse freigegeben wird?
wird also auch die ganze Tobjectlist "Pages" freigegebn wenn "project.free"
Delphi-Quellcode:
Demzufolge würde bei: Project.free ja auch Project.pages.last.pic "gefreet"; sowie alle anderen Objekte in "pages" (z.B. weitere Tobjectlists).
//Deklaration
Tproject=class save: Tsave; Pages: TseiteList; end; var project: Tproject; |
Re: Arbeiten mit Tobjectlist
Bei einer TObjectList kann man das Verhalten mit der Eigenschaft .OwnsObjects steuern.
|
Re: Arbeiten mit Tobjectlist
Das Problem ist aber, dass man beim Kreiren von Timage einen Owner angeben muss.. TObjectlist funktioniert als Owner nicht. Daher muss ich das im Moment extra freigeben. Kann man das irgendwie so gestalten, dass das Image bei Pages.delete(index) auch freigegeben wird. Genauso wie andere unterklassen? Manuell ist das ja recht aufwendig.
Das die Objektliste alle Objekte freigibt habe ich schon verstanden. Aber ich glaube, dass bei dem Freigeben eines Objekts, des Typs Tseite noch nicht von alleine auch das untergeordnete .pic (Timage) freigegeben wird. |
Re: Arbeiten mit Tobjectlist
Du kannst auch NIL als Owner angeben. Steht <Liste>.OwnsObjects auf True wird die Liste beim Hinzufügen automatisch der Eigentümer.
|
Re: Arbeiten mit Tobjectlist
Delphi-Quellcode:
Wenn ich nun im Programmcode ein Bild erzeuge:
Tseite=class
pic: Timage; //... end; Tproject=class save: Tsave; Pages: TseiteList; end; var project: Tproject;
Delphi-Quellcode:
wenn ich nun später das hier aufrufe:
project.pages:= Tseitelist.create; //Ownsobjects automatisch auf true
projec.pages.add(Tseite.create); project.pages.last.pic:=Timage.create(nil); //Bild erstellen project.pages.parent:=Mainform; //auf dem Bild wird nachfolgend was gezeichnet
Delphi-Quellcode:
so bleibt das Bild weiter auf der Form und ist nicht weg :/ wurde das also auch nicht freigegeben?
project.delete(0);//0= index von pages.last
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:54 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