Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Multipage-Support: Ich komme nicht weiter (https://www.delphipraxis.net/97945-multipage-support-ich-komme-nicht-weiter.html)

hansklok 19. Aug 2007 14:21


Multipage-Support: Ich komme nicht weiter
 
Hallo,

ich bin grade dabei ein Grafik-Programm zu schreiben. Projekte, die in diesem Programm erstellt werden, können gespeichert und wieder geladen werden. Bis dahin kein Problem, aber ich möchte, dass ein "Dokument" mehrere "Seiten" beinhalten kann. Und hier komme ich einfach nicht weiter. Ich habe eine Klasse TSeite:

Delphi-Quellcode:
  TSeite = class(TList)
  private
      Width:       Integer;
      Height:      Integer;
      Objekt:      Integer;
      Canvas:      TCanvas;
      Offset:      TBitmap;
      Raster:      TRaster;
      Hintergrund: THintergrund;
      Information: TInformation;
  public
      ...
  end;
Eine TSeite kann verschiedene grafische Objekte (Textfelder, Ellipsen etc.) enthalten. Nun möchte ich eine Klasse "TDokument" schreiben, eigentlich müsste diese ja auch von Typ TList sein, denn sie enthält ja mehrere Seiten. Ich komme aber mit meinem Denkansatz nicht weiter. Wie kann ich in ein TDokument eine neue TSeite einfügen, wie kann ich im TDokument nur eine bestimmte Seiten ansprechen? Versteht ihr mein Problem? Ich würde mich freuen, wenn wir gemeinsam ein Grundgerüst für diese Klasse entwickeln könnten.

Viele Grüße hansklok

Garfield 19. Aug 2007 14:29

Re: Multipage-Support: Ich komme nicht weiter
 
Zitat:

Zitat von hansklok
... Nun möchte ich eine Klasse "TDokument" schreiben, eigentlich müsste diese ja auch von Typ TList sein, denn sie enthält ja mehrere Seiten. ...

TList ist der Unit Classes deklariert:
Delphi-Quellcode:
  TList = class(TObject)
  private
    FList: PPointerList;
    FCount: Integer;
    FCapacity: Integer;
  protected
    function Get(Index: Integer): Pointer;
    procedure Grow; virtual;
    procedure Put(Index: Integer; Item: Pointer);
    procedure Notify(Ptr: Pointer; Action: TListNotification); virtual;
    procedure SetCapacity(NewCapacity: Integer);
    procedure SetCount(NewCount: Integer);
  public
    destructor Destroy; override;
    function Add(Item: Pointer): Integer;
    procedure Clear; virtual;
    procedure Delete(Index: Integer);
    class procedure Error(const Msg: string; Data: Integer); overload; virtual;
    class procedure Error(Msg: PResStringRec; Data: Integer); overload;
    procedure Exchange(Index1, Index2: Integer);
    function Expand: TList;
    function Extract(Item: Pointer): Pointer;
    function First: Pointer;
    function GetEnumerator: TListEnumerator;
    function IndexOf(Item: Pointer): Integer;
    procedure Insert(Index: Integer; Item: Pointer);
    function Last: Pointer;
    procedure Move(CurIndex, NewIndex: Integer);
    function Remove(Item: Pointer): Integer;
    procedure Pack;
    procedure Sort(Compare: TListSortCompare);
    procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil);
    property Capacity: Integer read FCapacity write SetCapacity;
    property Count: Integer read FCount write SetCount;
    property Items[Index: Integer]: Pointer read Get write Put; default;
    property List: PPointerList read FList;
  end;
Eventuell könnte man ein Array of TSeite verwenden.

Die Muhkuh 19. Aug 2007 14:31

Re: Multipage-Support: Ich komme nicht weiter
 
Ich werfe mal eine Delphi-Referenz durchsuchenTObjectList in den Raum. Damit ist das möglich, was Du vor hast (und spart das Array ;) )

DGL-luke 19. Aug 2007 14:32

Re: Multipage-Support: Ich komme nicht weiter
 
Entweder du baust dir deine eigene Listenklasse, oder du benutzt einfach TObjectList.

Delphi-Quellcode:
type
  TDokument = class
    Pages: TObjectList;
    //....
  end;

  //oder
  TDokument = class(TObjectList)
    //..
  end;

Garfield 19. Aug 2007 14:35

Re: Multipage-Support: Ich komme nicht weiter
 
Zitat:

Zitat von Die Muhkuh
... (und spart das Array ;) )

Sieht auch eleganter aus.

Die Muhkuh 19. Aug 2007 14:35

Re: Multipage-Support: Ich komme nicht weiter
 
Hi,

ich würde ja diese Aufteilung vorschlagen:

Delphi-Quellcode:
type
  TSeite = class(TObject)
  ...
  end;

  TDokument = class(TObjectList)
  private
    function GetSeite(Index: Integer): TSeite;
  public
    property Items[Index: Integer]: TSeite read GetSeite;
  end;

function TDokument.GetSeite(Index: Integer): TSeite;
begin
  Result := TSeite(inherited Items[Index]);
end;

hansklok 19. Aug 2007 14:40

Re: Multipage-Support: Ich komme nicht weiter
 
@ Die Muhkuh

Ich habe noch nie mit TObjectList gearbeitet, aber nach nächtlichen Dauer-Suchen hatte ich auch schon darüber nachgedacht, aber wie könnte ich z.B. eine neue Seite in das Dokument einfügen und es gilt ja auch zu beachten, dass wenn ein TDokument erstellt wird bereits eine Seite vorhanden sein soll!

Die Muhkuh 19. Aug 2007 14:44

Re: Multipage-Support: Ich komme nicht weiter
 
Hi,

hinzufügen geht z.B. so:

Delphi-Quellcode:
// Dokument: TDokument (irgendwo erzeugen^^)
var
  Seite: TSeite;
begin
  Seite := TSeite.Create(<evtl. ein Owner);
  Dokument.Add(Seite);

  // Zugriff auf Seite 1 wäre z.B.
  Seite := Dokument.Items[0];
  // Hier kannst Du nun was mit der Seite anstellen
end;

hansklok 19. Aug 2007 16:16

Re: Multipage-Support: Ich komme nicht weiter
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, ich habe mir schnell mal etwas zusammengebastelt (siehe Anhang). Ist der Aufbau so richtig und warum erscheint beim Schließen der Testanwendung die Fehlermeldung "Ungültige Zeigeroperation"?

@ Die Muhkuh:

Ich habe zwar schon von propertys gelsen/gehört, aber wie funktioniert das in Bezug auf meine Klasse bzw. welche Vorteile bringt mir das?

Delphi-Quellcode:
property Items[Index: Integer]: TSeite read GetSeite; ????
Für eure Hilfe wäre ich sehr dankbar!

MfG hansklok

Die Muhkuh 19. Aug 2007 16:21

Re: Multipage-Support: Ich komme nicht weiter
 
Hi,

Du brauchst die Seiten, die Du der ObjectList hinzufügst, nicht selbst wieder über Free zerstören, dass macht die ObjectList selbst. Dann gibst Du im Destructor von TDokument die Variable Offset frei (Offset.Free). Im OnDestroy der Form steht auch noch mal Offset.Free. Eins von beiden musst Du entfernen.

hansklok 19. Aug 2007 16:28

Re: Multipage-Support: Ich komme nicht weiter
 
... aber an sich ist es genau so, wie du es meintest, oder?

Und wie funktioniert das mit den properties?

Die Muhkuh 19. Aug 2007 16:32

Re: Multipage-Support: Ich komme nicht weiter
 
Hi,

noch nicht. Die greifst falsch auf die Seiten zu (per TSeite(Index) geht das nicht).

Zu den Properties: http://www.dsdt.info/grundlagen/sprache/oo.php Bei "Eigenschaften oder Properties" geht es los.

Die Property für die Dokumentklasse wäre, wie schon geschrieben:

Delphi-Quellcode:
property Items[Index: Integer]: TSeite read GetSeite;
Und anstatt dem Aufruf "TSeite(Index)", geht es dann über Items[Index].

hansklok 19. Aug 2007 16:39

Re: Multipage-Support: Ich komme nicht weiter
 
.. also
Delphi-Quellcode:
TSeite(Items[Index])
, weil sonst kann ich ja nicht auf die Seiteneigenschaften zugreifen, oder?

Die Muhkuh 19. Aug 2007 16:47

Re: Multipage-Support: Ich komme nicht weiter
 
Hi,

Items gibt eine TSeite zurück, da brauchst Du keinen Typecast mehr ;)

hansklok 19. Aug 2007 16:52

Re: Multipage-Support: Ich komme nicht weiter
 
He sorry, aber ich kapiere es grade überhaupt nicht mehr:

Zitat:

Items gibt eine TSeite zurück, da brauchst Du keinen Typecast mehr

Die Muhkuh 19. Aug 2007 16:57

Re: Multipage-Support: Ich komme nicht weiter
 
Hi,

also, nochmal langsam :-)

Wie auf DSDT.info steht, kann man mit einer property Lese- und Schreibzugriff auf eine Variable (ich sage mal) "überwachen". Mit Read überwacht man Lesezugriff und mit write Schreibzugriff. Bei unserer Items-Property gibt es aber nur ein Read, will heißen, man kann nur Lesen und nicht Schreiben:

Delphi-Quellcode:
property Items[Index: Integer]: TSeite read GetSeite;
Ruft man nun im Source Items[Index] auf, wird die Function GetSeite aufgerufen.

Delphi-Quellcode:
function TDokument.GetSeite(Index: Integer): TSeite;
begin
  Result := TSeite(inherited Items[Index]);
end;
Wie Du hier siehst, wird schon eine Seite zurückgegeben (Funktionen kennst Du ja bestimmt, nur statt hier ein Boolean, Integer oder String zurückgegeben wird, wird hier ein Object, eine TSeite, zurückgegeben).

Deswegen kannst Du auch direkt auf Items[Index].Width zugreifen und brauchst nicht TSeite(Items[Index].Width) schreiben.

Unter dem Stichwort Hier im Forum suchentypisierte Listen sollte noch mehr zu finden sein.

hansklok 19. Aug 2007 17:07

Re: Multipage-Support: Ich komme nicht weiter
 
Danke, da hab ich wieder etwas dazugelernt,

damit ergeben sich für mich ganz neue Programmiereigenschaften!

DP-Maintenance 19. Aug 2007 21:29

DP-Maintenance
 
Dieses Thema wurde von "Christian Seehase" von "Programmieren allgemein" nach "Object-Pascal / Delphi-Language" verschoben.
Ein delphispezifisches Problem.

hansklok 26. Aug 2007 15:39

Re: Multipage-Support: Ich komme nicht weiter
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

also mittlerweile habe ich das Grundkonzept umgesetzt. Im Anhang befindet sich ein Test-Projekt, in das man zunächst, eben nur zu Testzwecken, beliebig viele Seiten einfügen kann (jeder Seite kann eine individuelle Hintergrundfarbe zugewiesen werden). Nun habe ich für TSeite und TDokument Save und Load Prozeduren geschrieben. Leider scheiter ich an der Load Prozedure für TDokument. Theoretisch müsste das mit einer repeat until Schleife funktionieren, hab nur keine Ahnung wie. Würde mich freuen, wenn sich jemand mal das Test-Projekt ansieht und mir mit der Procedure TDokument.Load(Datei: TFileStream) helfen könnte!

Vielen Dank

hansklok

hansklok 26. Aug 2007 16:17

Re: Multipage-Support: Ich komme nicht weiter
 
... kann mir niemand helfen?

Die Muhkuh 26. Aug 2007 17:14

Re: Multipage-Support: Ich komme nicht weiter
 
Aye, pushen ist erst nach 24h erlaubt, Kapitän Hansklok.

Jedoch zu Deinem Problemchen, schlägt der Skipper das hier vor:

Delphi-Quellcode:
procedure TDokument.Save(Datei: TFileStream);
var
  i: Integer;
begin
  // Anzahl der Items reinschreiben:
  Datei.WriteBuffer(Count, SizeOf(Integer));

  for i:= 0 to Count-1 do
    Items[i].Save(Datei);
end;

procedure TDokument.Load(Datei: TFileStream);
var
  Seite: TSeite;
  I: Integer;
  J: Integer;
begin
  // Auslesen der Anzahl der Items

  Datei.ReadBuffer(I, SizeOf(Integer));

  for J := 0 to I - 1 do
  begin
    Seite := TSeite.Create(Form1.Offset, Form1.PaintBox1.Canvas);
    Seite.Load(Datei);
    Add(Seite);
  end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:32 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