Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Problem mit Listview und SmallImages (https://www.delphipraxis.net/179939-problem-mit-listview-und-smallimages.html)

Gutelo 12. Apr 2014 08:20

Problem mit Listview und SmallImages
 
Hallo,

ich habe eine TListView mit ViewStyle=vsList.

Mit einem Button-Klick soll das TListView sowohl mit Text-Eintraegen gefuellt werden als auch mit den zugehoerigen kleinen Icons. Im konkreten Fall ist es eine Liste von Laendern mit den jeweiligen Landesflaggen. Die Prozedur die beim Button-Klick aufgerufen wird sieht wie folgt aus:

Delphi-Quellcode:

procedure Plot_Listview(CSet : TCountrySet; LV : TListView);
var IL : TImageList;
    z : TCountries;
    i,j : integer;
begin
  // Falls SmallImages zugewiesen, dann loesche es
  if LV.SmallImages <> nil then LV.SmallImages.Free;
  LV.Clear;
  // Erstelle ImageList
  IL := TImageList.Create(nil);
  IL.Width := 16;
  IL.Height := 11;
  i := 0;
  // Lese alle Laender in der Menge CSet ein und fuege sie der Liste hinzu
  for z in CSet do
  begin
    LV.Items.Add;
    LV.Items[i].Caption := Get_Country(z);
    LV.Items[i].ImageIndex := i;
    IL.Add(Get_Flag_BMP(z),nil); // <- Fuege Flagge der ImageList hinzu
    Inc(i,1);
  end;
  // Zuweisung der ImageList an die Listview
  LV.SmallImages := IL;
  LV.SortType := stboth;
end;
Das Problem: Wenn ich einmal auf den Button-Klicke ist alles wie es sein soll. Wenn ich jedoch ein zweites mal klicke, dann stimmen die Flaggen nicht mehr: bei sehr wenigen Laendern sind die Flaggen richtig, bei den restlichen Laendern wird immer die gleiche Flagge angezeigt.

Ich vermute, dass der Fehler bei Listview selbst liegt (Zuordnung Item <-> Bild), da die Bilder in ListView.SmallImages auch nach dem zweiten Klick in Ordnung sind (habe ich testweise in einem separaten TImage anzeigen lassen).

Irgendjemand eine Idee dazu? Fuer mich wirkt es wie ein Bug bei TListView.

Gutelo

himitsu 12. Apr 2014 08:41

AW: Problem mit Listview und SmallImages
 
Delphi-Quellcode:
  LV.SmallImages.Free; // Free prüft auch nochmal auf nil
  LV.Clear;
  // Erstelle ImageList
  IL := TImageList.Create(Self); // wer gibt das frei, wenn die Form geschlossen wird?
Warum immer neu erstellen?
Einfacher wäre es, wenn du eine ImageList auf die Form legst, da auch gleich mit dem ListView verbindest und im Code die Liste nur noch leerst (ein kleiner Clear-Befehl).


Und es is eine echt blöde Idee, parallel mitzählen zu wollen.
- erstmal hat man dann die Daten/Positionen doppelt und wenn die mal nicht syncron laufen, dann steht alles schief
- und dann liefern viele Funktionen extra das zurück, was sie sind (der eigenen Index oder die Instanz)
Delphi-Quellcode:
procedure Plot_Listview(CSet : TCountrySet; LV : TListView; IL: TImageList=nil);
var z : TCountries;
begin
  if not Assigned(IL) then
    IL := LV.SmallImages;
  LV.Clear;
  IL.Clear;
  IL.Width := 16;
  IL.Height := 11;
  // Lese alle Laender in der Menge CSet ein und fuege sie der Liste hinzu
  for z in CSet do
    with LV.Items.Add do // verwende die Eigenschaten des "wirklich" neuen Eintrags (kann man auch gern in einer Variable zwischenspeichern)
    begin
      Caption := Get_Country(z);
      ImageIndex := IL.Add(Get_Flag_BMP(z), nil); // weise den Index zu, welcher "wirklich" dem neuen Bild entspricht
    end;
  LV.SortType := stboth;
end;
Es kann auch sein, daß der Index vom Add zurückgegeben wird ... Dann natürlich als Index behandeln und nicht als Instanz. :angel:

30% weniger Codezeilen und dazu noch viel weniger Fehlerpotential (praktisch Keines).

Gutelo 12. Apr 2014 09:00

AW: Problem mit Listview und SmallImages
 
Himitsu, du bist mein Held :)

Zitat:

Warum immer neu erstellen?
Einfacher wäre es, wenn du eine ImageList auf die Form legst, da auch gleich mit dem ListView verbindest und im Code die Liste nur noch leerst (ein kleiner Clear-Befehl).
Ich weiss. Aber ich hasse diese On-Formular Komponenten weil sie beim Designen der Forms stoeren. Dass der Speicher nicht freigegeben wird bei Programmende ist mir bewusst.

Zitat:

Und es is eine echt blöde Idee, parallel mitzählen zu wollen.
- erstmal hat man dann die Daten/Positionen doppelt und wenn die mal nicht syncron laufen, dann steht alles schief
- und dann liefern viele Funktionen extra das zurück, was sie sind (der eigenen Index oder die Instanz)
Das Mitzaehlen hat genau das Problem verursacht. Nachdem ich es in dein With ... do Konstrukt umgeaendert habe geht es. So ganz verstehen tue ich es aber nicht, da i auf 0 initialisiert wird und danach item fuer item erhoeht wird.

Gutelo

himitsu 12. Apr 2014 10:25

AW: Problem mit Listview und SmallImages
 
cnPack oder so ... da gibt es Optionen wie NonVisual-Componenten ausblenden,
oder du verwendest DatenModule, welche dazu gedacht sind. :zwinker:

Zitat:

Zitat von Gutelo (Beitrag 1255401)
So ganz verstehen tue ich es aber nicht, da i auf 0 initialisiert wird und danach item fuer item erhoeht wird.

Bist du dir denn sicher, daß das erste Element auch immer den Index 0 bekommt? :stupid:

PS: Inc hat per Default immer 1, also
Delphi-Quellcode:
Inc(i)
geht auch.
Lässt sich für mich zumindestens auch besser lesen ... Ohne Wert ist es immer +1 und ansonsten muß ich mir erst die Zahl genauer ansehn.


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