Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   TStrings (ListBox.Items) ohne ".add" ? (https://www.delphipraxis.net/202701-tstrings-listbox-items-ohne-add.html)

MicMic 28. Nov 2019 21:14

Delphi-Version: 10.2 Tokyo

TStrings (ListBox.Items) ohne ".add" ?
 
Hallo,
kann man eigentlich auch die Anzahl der ListBox-Items direkt angeben?
"ListBox.Count:=10" geht natürlich nicht. Zur Zeit nutze ich in einer For-Schleife "ListBox.Items.Add(""); Der Inhalt wird anders befüllt und dachte mir, wenn ich "...items.add" mir sparen kann, dass es evtl. ein wenig schneller wird.

Gruß Mic

DieDolly 28. Nov 2019 21:22

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Du kannst BeginUpdate vor und EndUpdate nach der Schleife nutzen. Das sollte das alles etwas beschleunigen wenn das dein Problem ist.

Michael II 28. Nov 2019 21:27

AW: TStrings (ListBox.Items) ohne ".add" ?
 
listbox1.Items.Count

hoika 28. Nov 2019 21:30

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Hallo,
Zitat:

kann man eigentlich auch die Anzahl der ListBox-Items direkt angeben?
nein

Zitat:

Der Inhalt wird anders befüllt
hm, warum füllst Du die ListBox nicht sofort mit den anders befüllten Werten,
anstatt erst mal leere Strings einzutragen?

MicMic 28. Nov 2019 21:40

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Danke für die Info. Begin/Endupdate habe ich schon.
Habe eben kurz was gefunden. In meiner For-Schleife habe ich mal mit eine String-Variabel rumprobiert. Also ct := ct + ', '; und außerhalb der Schleife mit "items.commatext := ct" die Anzahl gesetzt. Aber das ist auch nicht schneller, als wie gehabt "items.add('')" in der Schleife zu nutzen.
Zitat:

hm, warum füllst Du die ListBox nicht sofort mit den anders befüllten Werten,
anstatt erst mal leere Strings einzutragen?
Die Werte bestehen nicht nur aus einen Text. Auch sieht meine ListBox ganz anders aus. Trotzdem brauche ich "items.add" damit DrawItem richtig funktioniert für meine Sache. Dachte nur, ich kann mir das "add" sparen und die Anzahl direkt setzen. Scheint aber wohl nicht zu gehen.

hoika 28. Nov 2019 21:44

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Hallo,
gehen tut das schon

https://docs.microsoft.com/en-us/win...ls/lb-setcount

Aber es bringt Dich hier nicht weiter, wegen der dort genannten Einschränkungen.

DieDolly 28. Nov 2019 21:49

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Habe eben kurz was gefunden. In meiner For-Schleife habe ich mal mit eine String-Variabel rumprobiert. Also ct := ct + ', '; und außerhalb der Schleife mit "items.commatext := ct" die Anzahl gesetzt. Aber das ist auch nicht schneller, als wie gehabt "items.add('')" in der Schleife zu nutzen.
Kannst du hier einen Beispielcode posten mit der Schleife und allem?

MicMic 28. Nov 2019 21:55

AW: TStrings (ListBox.Items) ohne ".add" ?
 
@hoika, danke für die Info. Gleich gelesen... nur 32767 Items. Zu wenig :)

@DieDolly
Nix besonderes...
Code:
Items.BeginUpdate;
For I := 0 To Length(D1)+Length(D2)-1 Do
Begin
 // hier zwischen drin hab ich noch anderes Zeug. Datenverarbeitung. Hat aber nix mit der ListBox direkt zu tun.
 Items.Add('');
End;
Items.EndUpdate;

MicMic 28. Nov 2019 22:06

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Was zum Beispiel auch Zeit kostet, ist die Listbox zu leeren. Also mit Clear.
Muss man zwar nicht immer machen aber manchmal halt schon.

Aber trotzdem mal Danke an alle. Das mit ".add" ist auch nicht so schlimm. Dachte nur, evtl. spare ich eine Sekunde, wenn ich hunderttausende Einträge irgendwie direkt setzen kann, als es mit ".add" zu machen.

Gute Nachtruhe und schöne Source-Code Träume :)

DieDolly 28. Nov 2019 22:12

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Dachte nur, evtl. spare ich eine Sekunde, wenn ich hunderttausende Einträge irgendwie direkt setzen kann,
Denk mal über VirtualStringTree (RootNodeCount, kein AddChild!) nach, wo du die Items selber auch zeichnest. Dürfte noch immer schneller sein.

Luckie 28. Nov 2019 22:37

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Bereite deine Daten so auf, dass du sie einzeln in einer Schleife in die Listbox schreiben kannst. Oder besser, schreib sie in eine Stringlist und Weise der Listbox zum Schluss die Stringlist zu.

DieDolly 28. Nov 2019 22:49

AW: TStrings (ListBox.Items) ohne ".add" ?
 
250.000x ListBox1.Items.Add() = ~3,8 Sekunden

StringList, 250.000x sl.Add() und dann ListBox1.Items.AddStrings() = 5,7 Sekunden.

Luckie 28. Nov 2019 22:54

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Kennt TListbox(.items) assign?

DieDolly 28. Nov 2019 23:01

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Ja. Dauert damit noch immer 5,4 Sekunden.

MicMic 28. Nov 2019 23:04

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Ich habe jetzt mal LB_SETCOUNT ($01A7) ausprobiert. Also "SendMessage(ListBox.Handle, $01A7, anzahl, 0);"

Auf der Microsoft Seite wird ja beschrieben, dass der Parameter wParam auf 16-Bit-Werte beschränkt ist. Also nicht mehr als 32767 Items steht da. Eine Info zu Windows 95/Windows 98/Windows Millennium Edition (Windows Me). Was andere BS-Versionen machen, steht da nicht. In nutze Windows 10 und habe es einfach mal probiert. Ein Test mit 136558 Items. Und es geht. Nun ohne ".add". Und es ist schneller :)

Sollte ich es mit Vorsicht nutzen? Meine Anwendung muss jedenfalls nicht mit Windows 95/Windows 98/Windows Millennium Edition (Windows Me) kompatibel sein.

MicMic 28. Nov 2019 23:14

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Nachtrag: Das mit dem "LB_SETCOUNT" hat auch noch einen positiven Effekt. Mein ListBox.Clear ist dadurch auch um einiges schneller.
Gerade alles zu schön um wahr zu sein. Mal schauen ob ich dadurch neue Fehler entdecke *lach

Michael II 28. Nov 2019 23:24

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Zitat von MicMic (Beitrag 1452435)
Das mit ".add" ist auch nicht so schlimm. Dachte nur, evtl. spare ich eine Sekunde, wenn ich hunderttausende Einträge irgendwie direkt setzen kann, als es mit ".add" zu machen.

Ich bin zwar nicht sicher, was du genau suchst... aber 100'000 Einträge aufs Mal in eine Listbox quetschen geht enorm viel schneller (als mit .add) so:

Delphi-Quellcode:
var hs : tstringlist;
  i: Integer;
begin
  hs := tstringlist.Create;
 try
  for i := 1 to 100000 do hs.Add( i.tostring );
  listbox1.Items := hs;
 finally
  hs.Free;
 end;
  showmessage( listbox1.items.count.tostring );
end;

Dabei habe ich soeben festgestellt, dass das Scrollen über den vertikalen Listbox-Scrollbalken nicht wirklich gut funktioniert. Ist das ein Delphi (10.3.3) oder ein Windows (Win10 19033) Problem?

Uwe Raabe 28. Nov 2019 23:29

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von MicMic (Beitrag 1452434)
@hoika, danke für die Info. Gleich gelesen... nur 32767 Items. Zu wenig :)

Das gilt nur für Windows 95/98/Me!

Folgendes kleine Beispielprogramm füllt die Listbox mit 250000 Einträgen in 20 ms. Ein nicht-virtuelles
Delphi-Quellcode:
Listbox1.Items.Add
mit BeginUpdate/Endupdate braucht hier 1616 ms.

Faktisch wird beim lbVirtual auch das LB_SETCOUNT benutzt. lbVirtual gibt es auch als lbVirtualOwnerDraw.

DeddyH 29. Nov 2019 06:13

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Welcher Benutzer scrollt eigentlich durch zigtausende Einträge?

hoika 29. Nov 2019 06:43

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Hallo,
Zitat:

wenn ich hunderttausende Einträge
Und er soll sich bei Deinen 100.000-en Einträgen zurecht finden?

Ganz klar der falsche Ansatz.
Biete vorher einen Filter an, der die Anzahl eingrenzt und gut is.

DieDolly 29. Nov 2019 08:06

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Ich bin zwar nicht sicher, was du genau suchst... aber 100'000 Einträge aufs Mal in eine Listbox quetschen geht enorm viel schneller (als mit .add) so:
Eben nicht. Das habe ich oben getestet und die Zeit mehrfach gemessen. Bei knapp 1,5 sekunden Unterschied kann man nicht mehr von Messtoleranz sprechen.

Frickler 29. Nov 2019 08:56

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Zitat von DeddyH (Beitrag 1452447)
Welcher Benutzer scrollt eigentlich durch zigtausende Einträge?

Ich denke, das ist für die berühmte völlig unscharfe Suche (*). Direkt scrollt da keiner. Aber über der Liste sind ein oder mehrere Suchfelder. Und da gibt man grob ein, was man so weiß, und unten wird live aufgelistet, was da bei rum kommt. Den Rest regelt das Gedächtnis des Bearbeiters... :) Je nach Datenbank kann es schneller sein, einfach alle Datensätze in die Listbox zu prügeln und dort dann zu filtern.

Für uns hat da immer noch das gute alte ClientDataSet gereicht.


----
(*) "Kam der Kunde nicht aus Koblenz? Hat den nicht die Müller bearbeitet? War der Vorgang nicht 2014 im Mai?" man kennt das...

hoika 29. Nov 2019 09:05

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Hallo,
Zitat:

Je nach Datenbank kann es schneller sein, einfach alle Datensätze in die Listbox zu prügeln und dort dann zu filtern.
Es ist bestimmt schneller, die in eine TStringList zu packen, als in eine TListBox.

Harry Stahl 29. Nov 2019 09:25

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1452446)
Zitat:

Zitat von MicMic (Beitrag 1452434)
@hoika, danke für die Info. Gleich gelesen... nur 32767 Items. Zu wenig :)

Das gilt nur für Windows 95/98/Me!

Folgendes kleine Beispielprogramm füllt die Listbox mit 250000 Einträgen in 20 ms. Ein nicht-virtuelles
Delphi-Quellcode:
Listbox1.Items.Add
mit BeginUpdate/Endupdate braucht hier 1616 ms.

Faktisch wird beim lbVirtual auch das LB_SETCOUNT benutzt. lbVirtual gibt es auch als lbVirtualOwnerDraw.

Das ist eindeutig die schnellste Variante.:thumb:

Und wenn man statt

"FListBox1Items.Add(I.ToString);"

einfach nur

"FListBox1Items.Add('');"

nutzt, sind es nur ca. 7 ms...

Übrigens gibt es wohl tatsächlich Probleme mit dem Scrollbalken, wenn Über ca. 60.000 Zeilen hinaus gescrollt werden soll.

Für die Anzeige so vieler Elemente kann man aber z.B. ein StringGrid nehmen, das aber nicht selber die Daten hält, sondern nur im DrawEvent auf die passenden Daten zugreift, die gerade auf dem Bildschirm angezeigt werden sollen. Da gibt es keine Probleme...

HeZa 29. Nov 2019 10:07

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Da ja bekannt ist wie viele Elemente eingefügt werden sollen, könnte es etwas bringen vorher Items.Capacity zu setzen (bei nicht virtueller Listbox).
Habe leider gerade kein Delphi zur Hand um das mal testen zu können.

Ciao Heza

Uwe Raabe 29. Nov 2019 10:26

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Zitat von HeZa (Beitrag 1452462)
Da ja bekannt ist wie viele Elemente eingefügt werden sollen, könnte es etwas bringen vorher Items.Capacity zu setzen (bei nicht virtueller Listbox).

Das TListBox.Items eine TListBoxStrings-Instanz ist, die SetCapacity nicht überschreibt, wird dort lediglich die leere Implementierung von TStrings ausgeführt. Bringt also rein gar nichts.

Diese TListBoxStrings-Klasse hat nur wenig mit einer TStringList gemein, was die üblichen Optimierungstechniken in der Regel scheitern lässt. Lediglich BeginUpdate/EndUpdate führt den entsprechenden WM_SETREDRAW Aufruf durch. Deswegen ist Assign auch langsamer als eine Folge von Add-Aufrufen, da bei Assign nach jedem Add auch noch ein PutObject folgt, was wiederum eine LB_SETITEMDATA Message sendet.

Rolf Frei 29. Nov 2019 10:32

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Listbox.Items.Text := #13#10#13#10#13#10#13#10#13#10#13#10#13#10#13#10#1 3#10#13#10;

So hast du 10 Leerzeilen.

Uwe Raabe 29. Nov 2019 11:16

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Zitat von Rolf Frei (Beitrag 1452464)
Listbox.Items.Text := #13#10#13#10#13#10#13#10#13#10#13#10#13#10#13#10#1 3#10#13#10;

So hast du 10 Leerzeilen.

Macht am Ende auch wieder 10 Add-Calls.

MicMic 29. Nov 2019 12:14

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Wichtig wäre noch zu erwähnen, wenn man nun das "lbVirtualOwnerDraw" und "LB_SETCOUNT" nutzt, dass man (wenn man die Anzahl braucht) nicht "ListBox.Count", sondern "ListBox.Items.Count" nutzt. Mir ist das zufällig aufgefallen, weil eine Sache bei mir nicht mehr funktionierte und gesehen habe, dass ich "ListBox.Count" angegeben hatte und sonst überall "ListBox.Items.Count". Nur mal so zur Info.

DieDolly 29. Nov 2019 13:10

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Statt solcher Tricks die betriebssystemabhängig sind würde ich ganz einfach VirtualStringTree nutzen.

HeZa 29. Nov 2019 13:56

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1452463)
Das TListBox.Items eine TListBoxStrings-Instanz ist, die SetCapacity nicht überschreibt, wird dort lediglich die leere Implementierung von TStrings ausgeführt. Bringt also rein gar nichts.

Dann ist die Sache ja klar. Will man schnell sein, programmiert man eine virtuelle ListBox, ansonsten muss man sich mit der Performance von Add zufrieden geben.

Oder man überlegt nochmal, warum man so viele Items in eine ListBox pumpen will.

Ciao Heza

MicMic 29. Nov 2019 20:47

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

Zitat von DieDolly (Beitrag 1452474)
Statt solcher Tricks die betriebssystemabhängig sind würde ich ganz einfach VirtualStringTree nutzen.

Sicherlich hat diese und jene Komponente Vorteile. Ich hatte viel am Anfang ausprobiert und musste feststellen, dass eine ListBox doch am schnellsten ist und ich sie nach meinen Bedürfnissen gut anpassen kann.

DieDolly 29. Nov 2019 20:50

AW: TStrings (ListBox.Items) ohne ".add" ?
 
Zitat:

dass eine ListBox doch am schnellsten is
Dann hast du das VST nicht richtig genutzt :P
Ein VST ist um Welten schneller als eine ListBox, wenn man die Daten von der Oberfläche trennt.
Die Oberfläche eines VST kann man auch anpassen. Da gibt es quasi keine Grenzen.


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