Einzelnen Beitrag anzeigen

Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#1

Objekte mit Thread in eine Containerklasse laden

  Alt 26. Jan 2007, 15:21
Ich habe eine Klasse, die in einer Liste einzelne Objekte verwaltet. Dann hab eich eine Klasse mit der man die Eigenschaften der Objekte in einer Datei speichern kann (das Format ist unerheblich.) und eine Klasse mit der ich die Objekte wieder erzeugen und ihnen die gespeicherten Eigenschaften wieder zuweisen kann:

Die Containerklasse:
Delphi-Quellcode:
type
  TOnProgress = procedure(Sender: TObject; PercentDone: Integer) of object;
  TOnFinish = procedure(Sender: TObject) of object;

  TPageCollection = class(TList)
  private
    FOnProgress: TOnProgress;
    FOnSaveFinish: TOnFinish;
    FOnLoadFinish: TOnFinish;
    function GetItem(Index: Integer): TImageEnVect;
    procedure SetItem(Index: Integer; Item: TImageEnVect);
  protected
    procedure Notify(Ptr: Pointer; Action: TListNotification); override;
  public
    procedure Add(Item: TImageEnVect);
    procedure Insert(Index: Integer; Item: TImageEnVect);
    procedure Update(Index: Integer; Item: TImageEnVect);
    property Items[Index: Integer]: TImageEnVect read GetItem write SetItem;
    function FindItemByName(Name: String): Integer;
    procedure SavePages(const Filename: String);
    procedure LoadPages(const Filename: String);
    property OnProgress: TOnProgress read FOnProgress write FOnProgress;
    property OnSaveFinish: TOnFinish read FOnSaveFinish write FOnSaveFinish;
    property OnLoadFinish: TOnFinish read FOnLoadFinish write FOnLoadFinish;
  end;
Laden und Speichern:
Delphi-Quellcode:
  // parent class with shared properties and methods
  TSaveLoad = class(TThread)
  private
    FFilename: string;
    FPages: TPageCollection;
    FIEVect: TImageEnVect;
    FPercentDone: Integer;
    FSize: Int64;
    FCurrentPos: Int64;
    FOnProgress: TOnProgress;
    //FOnFinish: TOnFinish;
    procedure SetFilename(const Filename: string);
    function GetFilename: string;
    procedure SetPages(const Value: TPageCollection);
    function GetPages: TPageCollection;
    procedure SetProgress(Sender: TObject; Size, CurrentPos: Int64);
    procedure DoProgress;
  public
    property Filename: string read GetFilename write SetFilename;
    property Pages: TPageCollection read GetPages write SetPages;
    property OnProgress: TOnProgress read FOnProgress write FOnProgress;
    //property OnFinish: TOnFinish read FOnFinish write FOnFinish;
  end;

  // Loading
  TLoad = class(TSaveLoad)
  private
    FOnLoadFinish: TOnFinish;
    procedure DecompressFiles(const Filename, DestDirectory: string);
    procedure DoFinish;
  protected
    procedure Execute; override;
  public
    property OnLoadFinish: TOnFinish read FOnLoadFinish write FOnLoadFinish;
  end;
Execute sieht so aus:
Delphi-Quellcode:
procedure TLoad.Execute;
var
  XMLFile : string;
  XMLDoc : DomDocument;
  XMLDomList : IXMLDOMNodeList;
  XMLNode : IXMLDOMNode;
  i, j : Integer;
begin
  if FileExists(FFilename) then
  begin
    DecompressFiles(FFilename, ExtractFilePath(ParamStr(0)));

    XMLFile := ExtractFilePath(ParamStr(0)) + ChangeFileExt(ExtractFilename(FFilename), '.xml');

    try
      CoInitialize(nil);

      XMLDoc := CoFreeThreadedDOMDocument.Create;
      XMLDoc.Load(XMLFile);

      // Seiten laden
      XMLDomList := XMLDoc.selectNodes('/root/pages/*');
      for j := 0 to XMLDomList.length - 1 do
      begin
        // Seite (TImageEnVect) erzeugen
        FIEVect := TImageEnVect.Create(nil);
        FIEVect.Name := Format('Page%d', [j]);
        // Layer laden
        XMLDomList := XMLDoc.selectNodes('/root/pages/singlepage/layers/*');
        for i := 0 to XMLDomList.length - 1 do
        begin
          with FIEVect do
          begin
            LayersAdd;
            XMLNode := XMLDomList.item[i].selectSingleNode('posx');
            Currentlayer.PosX := StrToInt(XMLNode.text);
            // ...;
            CurrentLayer.Bitmap.VclBitmap.LoadFromFile(ExtractFilepath(ParamStr(0)) + XMLNode.text);
          end;
        end;
        // Textobjekte laden
        XMLDomList := XMLDoc.selectNodes('/root/pages/singlepage/textobjects/*');
        for i := 0 to XMLDomList.length - 1 do
        begin
          with FIEVect do
          begin
            ObjKind[-1] := iekTEXT;
            // ...;
            AddNewObject;
          end;
        end;
        // Seite (TImageEnVect) zur Liste hinzufügen
        Pages.Add(FIEVect);
      end;
    finally
      CoUninitialize;
    end;
  end
  else
    raise Exception.CreateFmt(rsFileNotExists, [FFilename]);
  if Assigned(OnLoadFinish) then
    OnLoadFinish(self);
end;
Wie bekomme ich jetzt aber die Objekte in die Containerklasse rein? Ich habe es so probiert:
Delphi-Quellcode:
procedure TPageCollection.LoadPages(const Filename: String);
var
  Load: TLoad;
begin
  Load := TLoad.Create(True);
  try
    Load.FreeOnTerminate := True;
    Load.Pages := self;
    Load.Filename := Filename;
    Load.OnProgress := OnProgress;
    Load.OnLoadFinish:= OnLoadFinish;
    Load.Resume;
  finally

  end;
end;
Aber irgendwie sind die Objekte in der Conainerklasse doch nicht da, obwohl sie da zu sein scheinen:
Delphi-Quellcode:
procedure TForm1.OnLoadFinish(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to PageCollection.Count - 1 do
    ListBox1.Items.Add(Format('Seite %d', [i+1]));
  LBCurrentIndex := 0;
  Progressbar1.Position := 0;
end;
Das funktioniert noch. Aber das:
Delphi-Quellcode:
procedure TForm1.ListBox1Click(Sender: TObject);
var
  idx : Integer;
begin
  idx := PageCollection.FindItemByName('Page' + IntToStr(LBCurrentIndex));
  if idx <> -1 then
  begin
    // aktuelle Seite sichern
// PageCollection.Update(idx, ImageEnVect);
// LBCurrentIndex := Listbox1.ItemIndex;
    // ausgewählte Seite anzeigen
    if not Assigned(ImageEnVect) then
      ImageEnVect := NewPage;
    if not Assigned(PageCollection.Items[idx]) then
      ShowMessage('Mist');
    ImageEnVect.Visible := False;
    ImageEnVect := PageCollection.Items[LBCurrentIndex];
    ImageEnVect.Visible := True;
  end;
  lblCurrPage.Caption := Format('Aktuelle Seite: %s', [PageCollection.Items[LBCurrentIndex].Name]);
end;
funktioniert nicht mehr. Als Objektname wird mir immer der Name des ersten Objektes angezeigt. Egal auf welchen Eintrag ich in der Listbox klicke. Und anzeigen tut er es mir auch nicht. Ich habe keine Ahnung, was da passiert. Sieht jemand von euch, was ich da falsch mache?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat