Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Listview aktualisieren und zur selben Position kommen
acnut - Mo 18.07.11 18:22
Titel: Listview aktualisieren und zur selben Position kommen
ich hab schon alles durchprobiert und das ding funzt einfach nicht. nach jedem update des listviews springt das ding einfach wieder nach oben.
hab onkel google gefragt, auch er kann mir nicht weiterhelfen :(
also mit diesem procedure füge ich alle items&subitems in das listview
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: 30: 31: 32: 33: 34: 35: 36: 37:
| procedure TForm1.DoAfterUpdateProcesses(Sender: TObject); var Process: TProcessItem; ListItem : TListItem; i : integer; CurrentItem : string; begin if DontUpdateList then Exit;
ListView1.Items.BeginUpdate; try if Assigned(ListView1.Selected) then CurrentItem := ListView1.Selected.Caption; ListView1.Clear; for I := 0 to ProcessInfo1.RunningProcesses.Count- 1 do begin Process := ProcessInfo1.RunningProcesses[i]; ListItem := ListView1.Items.Add; ListItem.SubItems.Add(IntToStr(Process.ParentProcessID)); ListItem.Caption := IntToStr(Process.ProcessID); ListItem.SubItems.Add(IntToStr(Process.ThreadsCount)); ListItem.SubItems.Add(IntToStr(Process.PriorityClassBase)); ListItem.SubItems.Add(IntToStr(process.MemoryInfo.WorkingSetSize)); ListItem.SubItems.Add(Process.UserName); ListItem.SubItems.Add(Process.ExeFile); ListItem.Data := Process; end; ListView1.Selected := FindIdInList(ListView1,CurrentItem); if Assigned(ListView1.Selected) then ListView1.Selected.MakeVisible(False); finally ListView1.Items.EndUpdate; end; end; |
und hier die funktion damit ich die process id in der liste krieg und diese dann wieder vergleiche:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function TForm1.FindIdInList(ListView: TListView; const ID: string): TListItem; var I : Integer; begin Result := nil; for I := 0 to ListView.Items.Count-1 do begin if CompareStr(ListView.Items[I].Caption,ID) = 0 then begin Result := ListView.Items[I]; Exit; end; end; end; |
nun ist mein ansatz überhaupt richtig oder mach ich eigentlich die ganze zeit nur schwachsinn :) bitte helft mir ;)
mfg
ACnut
Narses - Mo 18.07.11 21:37
Moin!
acnut hat folgendes geschrieben : |
ist mein ansatz überhaupt richtig |
Also grundsätzlich würde ich sagen, ist das schon OK. Allerdings würde ich das Selektieren ausserhalb der Update-Klammer machen:
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: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| procedure TForm1.DoAfterUpdateProcesses(Sender: TObject); var Process: TProcessItem; ListItem : TListItem; i: Integer; CurrentItem: String; begin if DontUpdateList then Exit;
CurrentItem := ''; if Assigned(ListView1.Selected) then CurrentItem := ListView1.Selected.Caption; ListView1.Items.BeginUpdate; try ListView1.Clear; for i := 0 to ProcessInfo1.RunningProcesses.Count- 1 do begin Process := ProcessInfo1.RunningProcesses[i]; ListItem := ListView1.Items.Add; ListItem.SubItems.Add(IntToStr(Process.ParentProcessID)); ListItem.Caption := IntToStr(Process.ProcessID); end; finally ListView1.Items.EndUpdate; end; if (CurrentItem <> '') then begin ListView1.Selected := FindIdInList(ListView1, CurrentItem); if Assigned(ListView1.Selected) then ListView1.Selected.MakeVisible(False); end; end;
function TForm1.FindIdInList(ListView: TListView; const ID: String): TListItem; var i: Integer; begin for i := 0 to ListView.Items.Count-1 do begin Result := ListView.Items[i]; if (CompareStr(Result.Caption, ID) = 0) then Exit; end; Result := NIL; end; |
cu
Narses
jaenicke - Mo 18.07.11 21:44
Besser wäre allerdings die Items gar nicht alle zu löschen, sondern nur die ggf. überflüssigen zu löschen bzw. fehlende zu ergänzen.
Dann stellt sich das Problem gar nicht erst, da die Items gar nicht unnötig gelöscht werden, und schneller ist es auch noch.
acnut - Di 19.07.11 13:26
@Narses danke für den geänderten code allerdings ändern tut sich da gar nichts (war ja eig klar).
bin echt verzeifelt :(
@jaenicke also wie meinst du das? soll ich die process ids in einem array speichern und dann nach dem update dann mit der neuen liste vergleichen? und änderungen dann einfach darunter einfügen? und das geht wirklich schneller als die liste zu löschen und wieder einfügen?
gibt es vllt eine andere komponente mit der das updaten wirklich schön flüssig funktioniert?
mfg
acnut
Narses - Di 19.07.11 13:51
Moin!
acnut hat folgendes geschrieben : |
@Narses danke für den geänderten code allerdings ändern tut sich da gar nichts (war ja eig klar). |
Hm, probier das mal aus:
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: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| procedure TForm1.DoAfterUpdateProcesses(Sender: TObject); var Process: TProcessItem; ListItem : TListItem; i: Integer; CurrentItem: String; begin CurrentItem := ''; if Assigned(ListView1.Selected) then CurrentItem := ListView1.Selected.Caption; ListView1.Items.BeginUpdate; try ListView1.Clear; for i := 0 to ProcessInfo1.RunningProcesses.Count- 1 do begin Process := ProcessInfo1.RunningProcesses[i]; ListItem := ListView1.Items.Add; ListItem.SubItems.Add(IntToStr(Process.ParentProcessID)); ListItem.Caption := IntToStr(Process.ProcessID); end; finally ListView1.Items.EndUpdate; end; if (CurrentItem <> '') then begin ListItem := FindIdInList(ListView1, CurrentItem); ShowMessage(ListItem.Caption); ListView1.Selected := ListItem; if Assigned(ListView1.Selected) then ListView1.Selected.MakeVisible(False); end; end;
function TForm1.FindIdInList(ListView: TListView; const ID: String): TListItem; var i: Integer; begin for i := 0 to ListView.Items.Count-1 do begin Result := ListView.Items[i]; if (Result.Caption = ID) then Exit; end; Result := NIL; end; |
acnut hat folgendes geschrieben : |
soll ich die process ids in einem array speichern |
Wieso in einem Array, du hast doch eine Referenz in der .Data-Eigenschaft des ListItems. :nixweiss:
acnut hat folgendes geschrieben : |
und dann nach dem update dann mit der neuen liste vergleichen? und änderungen dann einfach darunter einfügen? und das geht wirklich schneller als die liste zu löschen und wieder einfügen? |
Naja, wenn es sehr viele Objekte sind, schon. Aber eine Prozessliste? Das sollte man kaum merken. :| Ich würde das erstmal so lassen und schauen, warum das mit dem Fokus nicht klappt, denn daran wird auch eine andere Komponente nix ändern. ;)
acnut hat folgendes geschrieben : |
gibt es vllt eine andere komponente mit der das updaten wirklich schön flüssig funktioniert? |
Falsche Frage, jetzt wird
jaenicke dir gleich den VirtualStringTree ans Herz legen. 8) OK, ist auch besser, aber auch deutlich schwerer zu verstehen. :?
cu
Narses
jaenicke - Di 19.07.11 14:03
Ohne sich zu merken welcher Eintrag vorher als erster angezeigt wurde, kann das nicht klappen. Denn so wird nur der markierte wieder markiert und dieser auch sichtbar gemacht, aber die Scrollposition wird nicht wiederhergestellt. :nixweiss:
Dieser erste sichtbare Eintrag steht bei einer ListView in TopItem, bei einer TVirtualStringTree in TopNode und einer ListBox in TopIndex. Es reicht also hier zusätzlich TopItem.Index in eine Variable zu speichern und danach TopItem auf Items[OldTopIndex] zu setzen.
Narses - Di 19.07.11 14:10
jaenicke hat folgendes geschrieben : |
Ohne sich zu merken welcher Eintrag vorher als erster angezeigt wurde, kann das nicht klappen. Denn so wird nur der markierte wieder markiert und dieser auch sichtbar gemacht, aber die Scrollposition wird nicht wiederhergestellt. :nixweiss: |
Von einer Scrollposition war bisher auch nicht die Rede. :idea: ;)
jaenicke hat folgendes geschrieben : |
Dieser erste sichtbare Eintrag steht bei einer ListView in TopItem, bei einer TVirtualStringTree in TopNode und einer ListBox in TopIndex. Es reicht also hier zusätzlich TopItem.Index in eine Variable zu speichern und danach TopItem auf Items[OldTopIndex] zu setzen. |
Theoretisch - ja. Praktisch ist allerdings zu berücksichtigen, dass sich die Liste verändert haben könnte und z.B. der Eintrag gar nicht mehr da ist oder die Differenz TopItemIndex zu SelectedItemIndex nicht mehr passen könnte. :shock: Ganz soo einfach ist das also auch nicht. Deshalb hätte ich gesagt, dass:
Delphi-Quelltext
1: 2:
| if Assigned(ListView1.Selected) then ListView1.Selected.MakeVisible(False); |
zwar unter Umständen einmal "Ruckelt", aber ausreichd ist.
cu
Narses
jaenicke - Di 19.07.11 14:16
Narses hat folgendes geschrieben : |
Ganz soo einfach ist das also auch nicht. |
Doch, zuerst den TopItem wiederherstellen und danach den zuletzt markierten falls vorhanden. ;-)
Und falls man auch den Eintrag aus dem TopItem wiederherstellen will, muss man eben dessen Inhalt speichern und danach suchen und nicht nur den Index. Dann kann man entweder nach Name oder bei Fehlschlag nach Index die Position wiederherstellen und wenn der zuletzt markierte noch existiert danach auch die Markierung.
Das habe ich hier gerade auch gemacht, wenn auch mit den VirtualTrees.
acnut - Di 19.07.11 14:25
aha jetzt funktionerts (thanks brother @Narses, i'm pushin' tethanks buttn for you!) :D
allerdings muss ich sehr schnell sein damit ich ein prozess auswählen kann sonst rutscht es wieder zur markierten stelle (war ja unser ziel :mrgreen:)
nun will ich jetzt weiterscrollen und nicht zur markierten stelle zurückspringen:
also in welchen on(mouseup,...od anderes)...events vom listview muss ich jetzt sozusagen ein "dontupdatelist" machen?
oder kann ich das so machen, so dass ich mit der änderung des scrollbars auch die position der markierten stelle erhöhe bzw. erniedrige?
mfg
ACnut
so sieht es mal zurzeit aus:
Moderiert von
Narses: Programm als Anhang hochgeladen.
jaenicke - Di 19.07.11 14:29
acnut hat folgendes geschrieben : |
also in welchen on(mouseup,...od anderes)...events vom listview muss ich jetzt sozusagen ein "dontupdatelist" machen?
oder kann ich das so machen, so dass ich mit der änderung des scrollbars auch die position der markierten stelle erhöhe bzw. erniedrige? |
Habe ich ja gerade geschrieben wie das geht. ;-)
acnut - Di 19.07.11 14:51
Zitat: |
Habe ich ja gerade geschrieben wie das geht. ;-) |
danke ich lese es gerade versteh aber nur cornflakes aber ohne milch. mehr saft bzw. milch wäre von vorteil :mrgreen:
also laut der delphi hilfe bekomme ich das:
Zitat: |
//
TopItem:
Gibt das oberste sichtbare Element einer Listenansicht an.
Mit TopItem können Sie das oberste sichtbare Element der Listenansicht ermitteln und daraus den Umfang eines vorangegangenen Bildlaufs ablesen. Eine Wertzuweisung an TopItem ermöglicht außerdem Der Wert der Eigenschaft TopItem kann nicht geändert werden.
// |
aber wird mit dem bildlauf einfach nur die anzahl der prozesse gemeint?
du hast geschrieben das ich den topitem speichern soll (ok kein problem) und wie mach ich das mit dem "oldtopindex"?
iwas hab ich da nicht verstanden bzw. ist mir unklar und ich kanns mir nicht vorstellen :(
Zitat: |
Theoretisch - ja. Praktisch ist allerdings zu berücksichtigen, dass sich die Liste verändert haben könnte und z.B. der Eintrag gar nicht mehr da ist oder die Differenz TopItemIndex zu SelectedItemIndex nicht mehr passen könnte. |
eben das verwirrt mich an diesem ganzen topitem-ding
Moderiert von
Narses: Zitat repariert.
jaenicke - Di 19.07.11 14:56
jaenicke hat folgendes geschrieben : |
Es reicht also hier zusätzlich TopItem.Index in eine Variable zu speichern |
Delphi-Quelltext
1: 2: 3: 4:
| var OldTopIndex: Integer; begin OldTopIndex := ListView1.TopItem.Index; |
jaenicke hat folgendes geschrieben : |
und danach TopItem auf Items[OldTopIndex] zu setzen. |
Delphi-Quelltext
1: 2:
| if OldTopIndex < ListView1.Items.Count then ListView1.TopItem := ListView1.Items[OldTopIndex]; |
acnut - Di 19.07.11 15:19
Delphi-Quelltext
1: 2:
| if OldTopIndex < ListView1.Items.Count then ListView1.TopItem := ListView1.Items[OldTopIndex]; |
schön und gut (jetzt versteh ich es glaube ich) allerdings ist topitem nur readonly. wie mach ich das jetzt? mit assign?
Tryer - Mi 20.07.11 05:12
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| var TpItemIndex: Integer; TpItemPos, Pos: TPoint; begin TpItemIndex := ListView.TopItem.Index; TpItemPos := ListView.TopItem.GetPosition;
Pos := ListView.Items[TpItemIndex].GetPosition; ListView.Scroll(Pos.X - TpItemPos.X, Pos.Y - TpItemPos.Y); end; |
Grüsse, Dirk
acnut - Mi 20.07.11 14:30
Tryer hat folgendes geschrieben : |
[delphi]var
TpItemIndex: Integer;
TpItemPos, Pos: TPoint;
begin
...
Grüsse, Dirk |
wenn ich mehrmals auf danke drücken dürfte, dann würde ich mindestens 20 mal weiter drücken ;)
erstens danke für Narses
zweitens danke für jaenicke
drittens danke für Tryer
ihr seid die coolsten ;)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!