Wolne działanie ListView

0

Cześć
Zacznę może od krótkiego opisu.

Aplikacja pobiera z tabeli około 1200 wpisów, to jest w zasadzie błyskawiczne, muszę to jednak wstawić do ListView i pogrupować. W sumie wszystkie rekordy (1200) będą w około 100 grupach. W prostej pętli For dopisuję kolejne rekordy i w razie czego uzupełniam grupy.

O ile samo dodanie rekordu nie jest problemem ListView.Items.Add(); podobnie jak uzupełnienie reszty danych to już dodanie grupy ListView.Groups.Add(); trwa wyraźnie za dłużej.

Zauważyłem, że czas ten rośnie im więcej jest grup. Przy około 30 grupach podanie kolejnej zajmuje około sekudnę. Można na to jakoś wpłynąć, przyspieszyć? Załadowanie do ListView 1200 rekordów trwa około minuty.

Z góry dzięki za sugestie.

2

Może popróbuj z beginUpdate?

0
Patryk27 napisał(a):

Może popróbuj z beginUpdate?

Pokombinowałem nieco i okazuje się, że wszystko działa szybciej jeżeli wpierw dodaję grupy, a później pozycje. Jeżeli grupy uzupełniam w trakcie dodawania pozycji to ListView strasznie spowalnia.
W tej chwili pomimo tego, że mam 2 pętle, pierwsza która tworzy grupy i druga która dopisuje pozycje do ListView, to działa to w zasadzie bez jakiegokolwiek opóźnienia...

Mam inne pytanie, tym razem związanie z wielkością czcionki użytej dla grup. Da się ją jakoś zmienić? Font obiektu ListView odnosi się tylko do pozycji. Grupy korzystają z czegoś innego. czego?

2

@amidar: każda kontrolka posiadająca możliwość przechowywania mnóstwa itemów obsługuje metody BeginUpdate i EndUpdate. Służą one właśnie po to, aby poinformować kontrolkę o tym, że zawartość będzie zmieniania. Dzięki temu po każdorazowej zmianie zawartości (edycji, wstawieniu czy usunięciu pozycji), kontrolka nie odświeża swojej zawartości, a więc nie marnuje czasu na absolutnie zbędne operacje (np. przemalowanie interfejsu). Dlatego też zawsze używaj tych metod, jeśli tylko są dostępne. A dostępne są przede wszystkim w ListView, ListBox, ComboBox itd.

Czyli aby mocno przyspieszyć uzupełnianie kontrolki w dane, na samym początku wywołaj ListView.BeginUpdate, następnie zrób co masz zrobić (dodaj dane) i na samym końcu zawołaj ListView.EndUpdate.

Ale kosmicznej optymalizacji nie ma się co spodziewać po użyciu tych metod. Równie dobrze wąskie gardło może być gdzieś indziej (czyli w samym kodzie pobierającym dane lub je grupującym).

amidar napisał(a):

Mam inne pytanie, tym razem związanie z wielkością czcionki użytej dla grup. Da się ją jakoś zmienić? Font obiektu ListView odnosi się tylko do pozycji. Grupy korzystają z czegoś innego. czego?

VCL domyślnie korzysta ze stylu systemowego, tak więc aby móc malować pozycje inaczej, można skorzystać ze zdarzeń pozwalających własnoręcznie je malować. Jest ich kilka, więc jest w czym wybierać.

Poczytaj: Vcl.ComCtrls.TCustomListView.OnDrawItem.

0

a sprawdzałeś może Virtual Treeview ?? Na pewno jest dużo szybszy niż Listview. Może akurat będzie Ci pasować.

0

@amidar: jeśli chcesz wiedzieć coś więcej to pokaż kod przygotowujący zawartość kontrolki – być może on też wcale nie jest jakiś specjalnie optymalny i to powoduje problem wydajnościowy.

0

Tam się nie za bardzo da to przyspieszyć, a @amidar już zrobił co mógł...
Pozostał Ci tylko tryb wirtualny, ale nie wiem czy jest sens.

NA Twoim miejscu zarzuciłbym całkowicie używanie TListView i zamienił go znakomitym Virtual-TreeView.
https://github.com/Virtual-TreeView/Virtual-TreeView/

Nie sugeruj się nazwą, ponieważ to jest wielokolumnowy TreeView, a więc może działać jak ListView.
Tylko lepiej, szybciej (pewnie 100x szybciej ; eee... to nieprawda, ponieważ "Virtual Treeview is extremely fast. Adding one million nodes takes only 700 milliseconds!*") i o naprawdę niebagatelnych możliwościach.
Tu więcej i łobrazki:
https://www.jam-software.com/virtual-treeview/features.shtml

0

Wielkie dzięki za wszelkie uwagi. BeginUpdate i EndUpdate dołożyłem, ale po zmianie kolejności dodawania elementów różnica nie jest już jakaś specjalnie wielka. Całe przeładowanie trwa poniżej sekundy... jest to akceptowalne w porównaniu do poprzednich 60 sekund ;)

Za to zainteresował mnie Virtual TreeView. Wygląda obiecująco, być może podmienię go jeszcze teraz zanim zabrnę za daleko ;)

1
amidar napisał(a):

Wielkie dzięki za wszelkie uwagi. BeginUpdate i EndUpdate dołożyłem, ale po zmianie kolejności dodawania elementów różnica nie jest już jakaś specjalnie wielka. Całe przeładowanie trwa poniżej sekundy... jest to akceptowalne w porównaniu do poprzednich 60 sekund ;)

Ha! Wiedziałem. :D

To też nie jest tak, że standardowe komponenty są jakoś szczególnie powolne (szczególnie szybkie też nie) – po prostu trzeba się nauczyć je obsługiwać. No i pozostaje jeszcze wydajność kodu pozyskującego dane, które dodajesz do kontrolki. W nim też może i można coś przyspieszyć, jednak bez kodu niczego więcej nie mogę napisać.

Żeby móc jeszcze bardziej zoptymalizować ten kod, trzeba by kuknąć do kodu tego komponentu i sprawdzić co wykonuje w danych przypadkach. W ten sposób można dojść do efektywnego (acz mniej czytelnego) rozwiązania. Choć pewnie nie ugra się tym zbyt wiele.

Za to zainteresował mnie Virtual TreeView. Wygląda obiecująco, być może podmienię go jeszcze teraz zanim zabrnę za daleko ;)

Na pewno warto poznać tę kontrolkę, bo daje niesamowite możliwości. Przykłady użytkowania możesz znaleźć w wyszukiwarce (przykładowe kody również). Standardowe kontrolki przydają się do prostych zastosowań, jednak do bardziej zaawansowanych i fikuśnych trzeba się gimnastykować i tu z pomocą przychodzi VirtualTreeView.

0

hmm, a nie szybciej by było wczytać i pogrupować te elementy w jakiejś tablicy a dopiero później, gdy już są odpowiednio ułożone wrzucić do listview?

1 użytkowników online, w tym zalogowanych: 0, gości: 1