![]() |
PNGImageList zu langsam / Alternative gesucht
Hi zusammen,
ich würde gerne die PngImageList verwenden transparente Icons an verschiedenen Stellen (Images, Menüs, Tabellen, ...) anzeigen zu lassen. Hierzu verwende ich knapp 100 Icons jeweils in 2 Größen (16x16 und 32x32), welche ich wie folgt (abgeschaut bei ![]()
Code:
Und dann beispielsweise wie folgt auf ein Image bringe
PngList := TPngImageList.Create(nil);
PngItem := PngList.PngImages.Add ; PngItem.PngImage.LoadFromFile(Filename);
Code:
Bei Laden konnte ich beobachten, wie folgende Methoden abgearbeitet werden:
ImageFront.Picture.Assign(PngList.PngImages[I].PngImage);
PngList.PngImages.Add (PngImages ist vom Typ TPngImageCollectionItems) -> TPngImageCollectionItem.Create -> TCollectionItem.Create -> TCollection.RemoveItem -> TList.Remove -> TList.IndexOf Beim IndexOf rennt der dann natürlich im Worst-Case über die gesammte Liste und zwar für jedes Icon, so dass ich eine Laufzeit von irgendwas in 0(n²) je PngImageList bekomme. Da ich jetzt leider auch noch zwei Listen habe - jeweils eine pro Icongröße - dauert der Vorgang bei mir eine knappe Minute, bis das Programm gestartet ist. Kann ich das irgendwie Beschleunigen ohne die Icon-Anzahl eingrenzen zu müssen? Folgende Ideen kamen mir dabei: - Irgendwie ein Array von TPngObjects auf die TPngList casten? - Nur eine Liste anlegen und daraus dann die andere per Skalieren der PNGs erzeugen? - Auf entweder die TCollection oder die TList verzichten (brauche ich wirklich beides?)? Weiterhin habe ich versucht, die TPngImageCollectionItems zu entfernen und durch eine von TObjectList abgeleitete Liste zu ersetzen. Das Laden ging dann zwar fühlbar schneller, aber die 16x16-Icons wurden dann nicht mehr angezeigt (die 32er wohl - komisch). Gibt es sonst vielleicht irgendwo ein Tutorial oder eine Anwendung in der ich mir die richtige Verwendung der PngImageList mal ansehen kann? (Google spuckt zur "PngImageList" bzw. "TPngImageList" jeweils lediglich drei Seiten aus und beim [ulr=http://www.delphipraxis.net/internal_redirect.php?t=111689&highlight=pngimagel ist]Secretizer[/url] finde ich die Verwendung der PngImageLists ilTreeIcons und ilGlyphs nicht). |
Re: PNGImageList zu langsam / Alternative gesucht
Verwende ImgList.PngImages.BeginUpdate und ImgList.PngImages.EndUpdate, das dürfte den Vorgang erheblich beschleunigen.
Edit: Beispiel ohne Fehlerbehandlung
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
const TimeFormat = 'nn:ss:zzz'; var I: Integer; StartTime, EndTime: TDateTime; TempFileName: String; TempImg: TPNGObject; TempBMP: TBitmap; RandomRect: TRect; C: TCanvas; begin TempBMP := TBitmap.Create; TempBMP.Width := 32; TempBMP.Height := 32; C := TempBMP.Canvas; C.Pen.Style := psSolid; C.Brush.Style := bsSolid; for I := 0 to 100 do begin C.Pen.Color := Random(clWhite); C.Brush.Color := Random(clWhite); RandomRect := Rect(Random(TempBMP.Width), Random(TempBMP.Height), Random(TempBMP.Width), Random(TempBMP.Height)); C.FillRect(RandomRect); end; TempFileName := IncludeTrailingPathDelimiter(GetEnvironmentVariable('Temp')) + 'PngImageListTest.png'; TempImg := TPNGObject.Create; TempImg.Assign(TempBMP); TempImg.SaveToFile(TempFileName); TempBMP.Free; TempImg.Free; StartTime := Now; ImgList.PngImages.BeginUpdate; for I := 0 to 300 do begin ImgList.PngImages.Add(False).PngImage.LoadFromFile(TempFileName); end; ImgList.PngImages.EndUpdate; EndTime := Now; Label1.Caption := 'Total: ' + FormatDateTime(TimeFormat, EndTime - StartTime); end; |
Re: PNGImageList zu langsam / Alternative gesucht
Vielen Dank Dani :thumb:
Dank deinem Beispiel klappts jetzt in unter einer Sekunde. Wie bist du darauf gekommen die BeginUpdate und EndUpdate zu verwenden? ist das unter Delphi gängige Praxis, oder gabs dazu irgendwo Hinweise? Vg, Spes |
Re: PNGImageList zu langsam / Alternative gesucht
Bin den Code per Debugger durchgegangen und dort wurde nach jeder Einfügeoperation die Update-Methode der TPngImageCollectionItems aufgerufen:
Delphi-Quellcode:
wobei CopyPngs so aussieht:
procedure TPngImageCollectionItems.Update(Item: TCollectionItem);
begin inherited Update(Item); if FOwner is TPngImageList then TPngImageList(FOwner).CopyPngs; end;
Delphi-Quellcode:
...dann erst hab ich die Methoden BeginUpdate und EndUpdate entdeckt, hatte vorher keine Ahnung. :stupid:
procedure TPngImageList.CopyPngs;
var I: Integer; Png: TPNGObject; Icon: HIcon; begin //Are we adding a bunch of images? if FLocked > 0 then Exit; {... danach werden alle PNGs neu erstellt} Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:14 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 by Thomas Breitkreuz