Autor Beitrag
msphp
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20

WIN 2000
D6 Pers
BeitragVerfasst: Do 04.08.05 09:39 
Hallo

Ich schreibe gerade an einem kleinen messageviewer, also einem programm mit dem man meldungen ein wenig Ordnen und durchstöbern kann. Alle Nachrichten-Eigenschaften (wie titel, grösse usw.) werden in ein TListView gefüttert. Soweit so gut. Jetzt habe ich zwei typen von Meldungen, nämlich Private nachrichten und Bulletins. Jetzt möchte ich gerne je nach bedarf nur Bulletins oder nur Private Nachrichten anzeigen. Lösungsansatz wäre klar: Inhalt vom Listview löschen, und dan nochmals die nachrichten laden und halt eben nur Private oder Bulletins. Was mich bis jetzt daran stört: das einlesen in der rund 1000 Zeilen dauert etwa 5 sekunden, nun frag ich mich ob es nicht die möglichkeit gäbe, selektierte Zeilen einfach auszublenden aus den Listview. Ich habs schon mit rauskopieren versucht in ein zweites Listview:
ausblenden Delphi-Quelltext
1:
2:
  for i:=0 to listview1.Items.Count-1 do
  listview2.Items.AddItem(listview1.Items.Item[i]);

was aber zu sehr komischen, nicht enden wollenden Fehlern beim Schliessen des Programmes führt.
Hat vieleicht noch jemand eine Idee wie ich das angehen könnte, auf irgend eine Art einen Teil der Listeneinträg temporär zu entfernen?

Vielen Dank für eure Hilfe :)

Michael
da_cara
Hält's aus hier
Beiträge: 12

Win XP SP2
D7 Ent
BeitragVerfasst: Do 04.08.05 09:57 
Was ist / sind Bulletins? :?:

Sollen denn alle Selektierten entfernt werden, oder alle Privaten und Bulletins?

Wenn alle z.b. Privaten Nachrichten angezeigt werden sollen, dann hast du sicher ein File in den die Nachrichten gespeichert sind. Dann würde ich beim Einlesen alle Nachrichten mit einem Parameter versehen. In diesem Fall für Privat und Bulletins. So könntest du sie in den Zwischenspeicher packen, als StringList oder weiss der Teufel und immer jeweils ausfiltern. Kostet natürlich Speicher und frisst performance, aber ich sehe da atm kein anderen Lösungsweg. Hab auch noch nicht gross drüber nachgedacht.

Wenn du es dann so machen würdest würde ich die nicht erwünschten mit

ausblenden Delphi-Quelltext
1:
Listview1.Items.Delte(I)					

löschen.

MFG Cara
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 04.08.05 10:19 
@da_cara: In deinem Source fehlt ein e, da steht Delte statt Delete...

Aber dies ist gar nicht das Problem! Das Problem ist, dass das Einlesen so lange dauert, und das ist kein Wunder, wenn das gleichzeitig sofort nachgezeichnet wird...

Lösung:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
ListView1.Items.BeginUpdate;
//Hier die Einträge löschen und hinzufügen
ListView1.Items.Clear;
//ListView1.Items.Add...
ListView1.Items.EndUpdate;

Da werden die 1000 Einträge nur noch einen Bruchteil einer Sekunde dauern...


Zuletzt bearbeitet von jaenicke am Do 04.08.05 11:26, insgesamt 1-mal bearbeitet
msphp Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20

WIN 2000
D6 Pers
BeitragVerfasst: Do 04.08.05 10:28 
Also Private und Bulletins sind nur einfach zwei typen von Meldungen. Private geht an eine einzige Person, Bulletins gehen an alle.

Das Begin- und EndUpdate hat leider so gut wie keinen Einfluss auf die Dauer des ladevorgangs des Listview.
magnoz
Hält's aus hier
Beiträge: 2

Debian, WinXP, ReactOS, BeOS
D5 Ent, D2005 Ent
BeitragVerfasst: Do 04.08.05 10:40 
hi,

steig auf den VirtualStringTree von Mike Lischke um :)
Bei dem kann man einzelne Eintrage in-/visible machen. Und ausserdem ist der viiieeeeel Schöner ;) Scherz beiseite, die Komponente ist einfach nur geil, schneller und hat wesentlich größeren Funktionsumfang als das normale TListView.

Ansonsten kann ich mich den Vorrednern nur anschließen, wenn du BeginUpdate und Endupdate verwendest, sollte es kein PRoblem bei 1000 Einträgen geben. Und dann kannst Du auhc gezielt einzelne löschen. Finde ich aber nicht so schick.

Gruß
KEn
msphp Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20

WIN 2000
D6 Pers
BeitragVerfasst: Do 04.08.05 11:00 
Also das hab ich schon eingebaut, das begin und endupdate, daran liegts nicht. Ich poste mal den quelltext der Schleife die das Items der Listview füllt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
  result.BeginUpdate;
  for  i:=0 to L-1 do
  begin
    IsBulletin:=(65536 and msgs[i].Status) <> 0;
    if (isBulletin and bull) or ((not isBulletin) and priv) then
    begin
      ListItem:=result.Add;
      ListItem.Caption:=inttostr(Msgs[i].Nbr);
      ListItem.SubItems.Add(inttostr(Msgs[i].Size));
      ListItem.SubItems.Add(msgs[i].fTo);
      ListItem.SubItems.Add(msgs[i].fFrom);
      ListItem.SubItems.Add(decodeseconds(Msgs[i].OrgTime));
      ListItem.SubItems.Add(msgs[i].Title);
      ListItem.SubItems.Add(msgs[i].fAt);
      ListItem.SubItems.Add(decodesecond(Msgs[i].ArrTime));
      ListItem.SubItems.Add(decodesecond(Msgs[i].FwdTime));
      ListItem.SubItems.Add(msgs[i].ToBBS);
      ListItem.SubItems.Add(msgs[i].FwdBBS);
      ListItem.SubItems.Add(msgs[i].OrigBBS);
      Listitem.SubItems.Add(inttostr(i));
      if (1024 and msgs[i].Status) <> 0 then
      Listitem.ImageIndex:=1 else ListItem.ImageIndex:=0;
      if isBulletin then begin
      Listitem.ImageIndex:=ListItem.ImageIndex+2; nrBu:=nrBu+1; end else nrPr:=nrPr+1;
      fortschritt:=(i*100) div L;
      statusbalken;
    end;
  end;
    result.EndUpdate;


Kleine Erklärung: Die Nachrichten befinden sich im Array Msgs, array eines Records der alle Daten enthält die über eine Meldung bekannt sind. Die if entscheidung am anfang ist dazu da jedes mal wen neu geladen wird halt jeweils nur bulletins, oder nur private oder beide nachrichten einzureihen.

Vielen Dank für eure nette hilfe auf jeden Fall mal :) Muss wahrscheinlich damit leben so wie es ist, funktioniert ja auf jeden fall.
sahib
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: Do 04.08.05 11:10 
Hi.

Ich würde die Nachrichten in einer TList verwalten und in der ListView (OwnerData := True) im OnData Ereignis zeichnen. Schneller geht es eigentlich nicht. Dann ist der limitierende Faktor nur das Einlesen der Daten, nicht aber die Darstellung in der ListView. Und Du kannst eine Nachricht dann auch ganz einfach ausblenden.

Schau mal hier(www.delphi-forum.de/...43014&highlight=), im unteren Drittel ist ein Beispiel von mir dazu.

Christian
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 04.08.05 11:39 
Das liegt an was ganz was anderes! Nimm mal die Fortschrittsanzeige aus der Schleife raus, dann wirds deutlich schneller gehen!

Wenn du die unbedingt drin haben willst, dann teste auf
ausblenden Delphi-Quelltext
1:
2:
if i mod 100 = 0 then
  //fortschritt

oder so, damit nur jeder hundertste Durchlauf in die Fortschrittsanzeige kommt.

Bei jeder Änderung muss die nämlich neu gezeichnet werden und das verlangsamt das deutlich!
patrick
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 1481

WIN2k, WIN XP
D6 Personal, D2005 PE
BeitragVerfasst: Do 04.08.05 11:48 
und entfern die prozedur statusbalken (obwohl ich nicht weiß was da drin ist) am besten auch gleich oder verschieb sie in den von jaenicke vorgeschlagenen abrage.

_________________
Patrick
im zweifelsfall immer das richtige tun!!!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 04.08.05 11:51 
Die meinte ich damit natürlich auch, denn die zeigt sicherlich den Fortschritt dann an, fortschritt ist ja wohl nur ne Integer-Variable... :wink:
da_cara
Hält's aus hier
Beiträge: 12

Win XP SP2
D7 Ent
BeitragVerfasst: Do 04.08.05 12:05 
user profile iconmagnoz hat folgendes geschrieben:
hi,

steig auf den VirtualStringTree von Mike Lischke um :)
Bei dem kann man einzelne Eintrage in-/visible machen. Und ausserdem ist der viiieeeeel Schöner ;) Scherz beiseite, die Komponente ist einfach nur geil, schneller und hat wesentlich größeren Funktionsumfang als das normale TListView.


Kannst die Komponente mal als Anhang hier reinstellen? Würde mich mal Interessieren, da ich persöhnlich auch einige Eigenschaften von TListView vermisse.

Danke im vorraus Cara
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 04.08.05 12:32 
:?: :?: :?:
Die Komponente ist doch frei im Internet verfügbar! Wo liegt das Problem?

Einfach mal bei Google suchen: Suche bei Google VIRTUALSTRINGTREE DOWNLOAD
Gleich das erste Ergebnis ist schon die Seite, auf der ganz unten auch der Download zu finden ist!!!

Als Anhang hat die Komponente hier nix verloren!
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Do 04.08.05 13:09 
Hallo,

mal ein Vorschlag:
Zwei ListView oder VirtualStringTree auf ein PageControl verwenden, dann braucht man es nur einmal zu initialisieren und kann bei Bedarf zum entsprechenden TabSheet wechseln.

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
msphp Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20

WIN 2000
D6 Pers
BeitragVerfasst: Do 04.08.05 13:14 
1. Statusbalken

Den hab ich mal raus genommen und wieder eingesetzt, hat nicht all zu grossen einfluss auf die geschwindigkeit. Behalte ihn lieber damit ich sehe dass mein progi noch am arbeiten ist. Macht auch nicht sonderlich vil, nur n viereckchen zeichnen. Aber danke für den Tip mit der aktualisierung nur alle paar schritte, hab ich natürlich eingebaut, macht noch sinn :)

2. Virtual Mode

Ich hab den Virtualmode bereits in der Delphi hilfe entdeckt, auch mit dem Hinweis auf Performance und so bei sehr vielen Listeneinträgen. Einfach halt mit dem Nachteil dass es nicht mehr so konfortabel ist. Ich werde mich mal dem annehmen mal sehen ob ich was schlaues hin kriege :P
sahib
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: Do 04.08.05 17:09 
user profile iconmsphp hat folgendes geschrieben:
2. Virtual Mode

Ich hab den Virtualmode bereits in der Delphi hilfe entdeckt, auch mit dem Hinweis auf Performance und so bei sehr vielen Listeneinträgen. Einfach halt mit dem Nachteil dass es nicht mehr so konfortabel ist. Ich werde mich mal dem annehmen mal sehen ob ich was schlaues hin kriege :P

Der Komfort besteht darin, dass Du a) eine immense Geschwindigkeit bekommst - es wird nur das gezeichnet, was sichtbar ist. Weiterhin, b), ist der Speicherbedarf geringer, da Du ihn verwaltest und nicht die Komponente, und c) kannst Du ganz einfach Deine Anzeige variieren, je nachdem, was Du angezeigt haben möchtest. Du wirst den virtuellen Mode der Standard-ListView zu schätzen lernen. Und deswegen gleich immer VirtualListView von Gems installieren?