Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Arbeiten mit Tobjectlist (https://www.delphipraxis.net/147670-arbeiten-mit-tobjectlist.html)

KahPee 13. Feb 2010 17:40


Arbeiten mit Tobjectlist
 
Hallo,

ich arbeite mit verschiedenen Objecten, die die Klasse TObjectlist beinhalten:
Delphi-Quellcode:
Tseite=class
    save: Tsave;
    pic: Timage;
    objects: TObjectlist;
  end;


  Tproject=class
    save: Tsave;
    Pages: Tobjectlist;
  end;
Nun habe ich ein Project deklariert und auch "kreirt"

Delphi-Quellcode:
var project: Tproject;
begin
project:=Tproject.Create
project.pages:=Tobjectlist.Create
Nun werden im Nachfolgenden Immer Objecte der Klasse Tseite project.pages zugefügt:
Delphi-Quellcode:
project.pages.add(TSeite.Create);
Und jetzt zu dem Problem, ich kann nicht auf "project.pages.Items[index].save" zugreifen..
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?

daywalker9 13. Feb 2010 17:43

Re: Arbeiten mit Tobjectlist
 
du musst die einzelnen items in der objectlist casten:

Delphi-Quellcode:
tSeite(project.pages.items[0]).save;
Oder von welchem typ auch immer deine Objekte in der List sind

mleyen 13. Feb 2010 17:44

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

KahPee 13. Feb 2010 17:53

Re: Arbeiten mit Tobjectlist
 
Delphi-Quellcode:
tSeite(project.pages.items[0]).save.saved:=true;
würde das Funktionieren (vorrausgesetzte Tsave enthält den Boolean save)?
Kann ich also die ObjeKte der Liste so direkt bearbeiten?

Noch eine Frage zu weiteren Verschachtelungen; ginge das dann auch so:
Delphi-Quellcode:
//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
mfg Kahpee

KahPee 13. Feb 2010 18:49

Re: Arbeiten mit Tobjectlist
 
Wird eigentlich Tseite(project.pages.last).pic freigegeben wenn:
Delphi-Quellcode:
Tseite(project.pages.last).delete;
//oder
project.pages.free
bzw. was für einen Owner muss ich beim Konstruieren des Image angeben um genau das zu erreichen?

Tseite(project.pages.last) funktioniert als Owner nicht, da Tseite mit Tcomponent inkompatibel ist.

himitsu 13. Feb 2010 19:07

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.

KahPee 13. Feb 2010 19:16

Re: Arbeiten mit Tobjectlist
 
Zitat:

Zitat von himitsu
Da diese untergeordneten Objekte zum Objekt gehören, sollten (gemäß den OOP-Regeln) diese auch nur von diesem Objekt erzeugt und freigegeben werden.

Versteh ich das also richtig, dass das so funktioniert wie ich mir das wünsche?

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?

generic 13. Feb 2010 19:34

Re: Arbeiten mit Tobjectlist
 
Zitat:

Zitat von mleyen
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

Man kann natürlich die TObjectlist ableiten (oder generics verwenden)
damit diese tseite zurück gibt und nicht tobject.

KahPee 13. Feb 2010 21:55

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 :(

daywalker9 13. Feb 2010 22:05

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;

KahPee 13. Feb 2010 22:15

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:
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;
Ansonsten nochmal zu der Frage mit den Konstruktoren. Was passiert mit
Delphi-Quellcode:
Tseite(project.pages.last).pic:=Timage.create(self)
wenn ich das hier ausführe:
Delphi-Quellcode:
Tseite(project.pages.last).delete;

daywalker9 13. Feb 2010 22:35

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;

KahPee 13. Feb 2010 22:44

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;

daywalker9 13. Feb 2010 22:48

Re: Arbeiten mit Tobjectlist
 
Delphi-Quellcode:
type
  TSeiteListe=Class(TObjectList)
  private
     function GetItem(Index: Integer): TSeite;
     procedure SetItem(Index:integer;Value:TSeite);
  public
    ....
  end;
Die Methoden fehlen natürlich noch in der deklaration der klasse. Dann funktioniert es.

KahPee 13. Feb 2010 22:53

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;

mkinzler 14. Feb 2010 08:55

Re: Arbeiten mit Tobjectlist
 
Man kann aber keine Integer nach TSeite casten

KahPee 14. Feb 2010 09:02

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 ;)

mkinzler 14. Feb 2010 09:05

Re: Arbeiten mit Tobjectlist
 
Lass den Cast einfach weg. :zwinker:

KahPee 14. Feb 2010 09:07

Re: Arbeiten mit Tobjectlist
 
du meinst ich brauch "function TseiteList.Last: Integer; " gar nicht neu zu definieren?

mkinzler 14. Feb 2010 09:08

Re: Arbeiten mit Tobjectlist
 
Eigentlich nicht

KahPee 14. Feb 2010 09:15

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?

mkinzler 14. Feb 2010 09:18

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

KahPee 14. Feb 2010 09:21

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:
//Deklaration
Tproject=class
    save: Tsave;
    Pages: TseiteList;
  end;

var project: Tproject;
Demzufolge würde bei: Project.free ja auch Project.pages.last.pic "gefreet"; sowie alle anderen Objekte in "pages" (z.B. weitere Tobjectlists).

mkinzler 14. Feb 2010 09:27

Re: Arbeiten mit Tobjectlist
 
Bei einer TObjectList kann man das Verhalten mit der Eigenschaft .OwnsObjects steuern.

KahPee 14. Feb 2010 09:37

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.

mkinzler 14. Feb 2010 09:44

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.

KahPee 14. Feb 2010 10:10

Re: Arbeiten mit Tobjectlist
 
Delphi-Quellcode:
Tseite=class
  pic: Timage;
  //...
end;

Tproject=class
    save: Tsave;
    Pages: TseiteList;
  end;
 

var project: Tproject;
Wenn ich nun im Programmcode ein Bild erzeuge:
Delphi-Quellcode:
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
wenn ich nun später das hier aufrufe:
Delphi-Quellcode:
project.delete(0);//0= index von pages.last
so bleibt das Bild weiter auf der Form und ist nicht weg :/ wurde das also auch nicht freigegeben?


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