Zapisywanie stanu TTreeView

1

Witam - posiadam na formie komponent TTreeView, który aktualizuję średnio co sekundę, wygląda to tak:
img1.png
(dorabiam nowy ficzer do mojego edytora ;P)

Problem jest w tym, że aktualizacja tego komponentu wymaga jego całkowitego wyczyszczenia i tworzenia wszystkich node-ów na nowo, przez co po aktualizacji całe TTreeView jest całkowicie zwinięte, podczas gdy ja chciałbym, aby pozostało w takim stanie, jakim było przedtem.

Pytanie: jak tego dokonać? Jak zapisać stan TTreeView, by później móc go przywrócić?


Edit: mógłbym co prawda aktualizować tylko te node-y, które uległy zmianie, lecz byłoby to nieco wolne w momencie, kiedy byłoby ich naprawdę sporo... Edit2: in fact, zaimplementuję to powyższe i zobaczymy, co wyniknie ;-; Niemniej, jestem otwarty na inne sugestie.
1

Nie wiem czy o to chodzi, ale

TreeView1.Items[i].Expanded - określa czy gałąź jest rozwinięta.
TreeView1.Items[i].Expand()  i  TreeView1.Items[i].Colapse() - rozwija i zwija daną gałąź

Trzeba by więc przelecieć wszystkie itemy i zapisać które są rozwinięte.

1
Patryk27 napisał(a)

Problem jest w tym, że aktualizacja tego komponentu wymaga jego całkowitego wyczyszczenia i tworzenia wszystkich node-ów na nowo, przez co po aktualizacji całe TTreeView jest całkowicie zwinięte, podczas gdy ja chciałbym, aby pozostało w takim stanie, jakim było przedtem.

Na pewno musisz kasować i tworzyć na nowo całe drzewo? To nie jest rozwiązanie, bo przy dużej ilości aktualizacja drzewa będzie trwała długo...

To co podał @ergo jest oczywiście rozwiązaniem, bo możesz zapisać stan gałęzi w jakiejś pomocniczej zmiennej/obiekcie, ale zwróć uwagę, że jeśli zapiszesz taki stan to po stworzeniu nowego drzewa i tak musisz sprawdzić które gałęzie i wartości są nowe, a które nie i te, które były przed aktualizacją odpowiednio zwinąć/rozwinąć;

Skoro i tak będziesz musiał sprawdzić co jest nowe a co nie, to równie dobrze możesz drzewo wyposażyć jedynie w nowe elementy, a stare pozostawić takie, jakimi były; Na pewno istnieje lepsze rozwiązanie i na pewno jest stosowane w innych IDE, więc trzeba takie coś wymyślić i zaimplementować - takie rozwiązanie będzie na pewno efektywniejsze i efektowniejsze; Jedynym minusem będzie prawdopodobnie większa ilość kodu do napisania, choć niekoniecznie;

Niestety nie wiem dokładnie jak wygląda obecny kod realizujący aktualizację drzewa, więc traktuj mój post jako teoretyczne rozważania;

Patryk27 napisał(a)

Edit: mógłbym co prawda aktualizować tylko te node-y, które uległy zmianie, lecz byłoby to nieco wolne w momencie, kiedy byłoby ich naprawdę sporo...

Na pewno? Według mnie wolniejsze będzie tworzenie całego nowego drzewa i rozwijanie wybranych gałęzi, niż aktualizacja pojedynczych elementów; Zwróć uwagę na to, że potrzebujesz tylko dodać kilka elementów, więc przy wspomnianych przez @marogo BeginUpdate i EndUpdate drzewo zaktualizuje się szybko, a przemalowanie go nastąpi tylko raz (bo przecież te metody do tego służą), stąd powinieneś zyskać na szybkości.

0
furious programming napisał(a):
Patryk27 napisał(a)

Edit: mógłbym co prawda aktualizować tylko te node-y, które uległy zmianie, lecz byłoby to nieco wolne w momencie, kiedy byłoby ich naprawdę sporo...

Na pewno? Według mnie wolniejsze będzie tworzenie całego nowego drzewa i rozwijanie wybranych gałęzi, niż aktualizacja pojedynczych elementów; Zwróć uwagę na to, że potrzebujesz tylko dodać kilka elementów, więc przy wspomnianych przez @marogo BeginUpdate i EndUpdate drzewo zaktualizuje się szybko, a przemalowanie go nastąpi tylko raz (bo przecież te metody do tego służą), stąd powinieneś zyskać na szybkości.

Problem byłby w usuwaniu node-ów, których już nie powinno być w drzewie (bo np.user usunął całą funkcję bądź zmienił jej nazwę) - musiałbym przechodzić po wszystkich listach przeparsowanych symbolów i sprawdzać, czy aby na pewno taka-a-taka funkcja/zmienna/przestrzeń nazw/typ się tam znajduje.


Well - najlepszym wyjściem z tej sytuacji jest imho rozwiązanie @ergo i to też spróbuję zaimplementować. Ew.po prostu zamiast drzewka aktualizowanego na żywo dodam jakąś opcję w menu or something, ale to jest raczej mało prawdopodobne rozwiązanie ;P
1
Patryk napisał(a)

Problem byłby w usuwaniu node-ów, których już nie powinno być w drzewie (bo np.user usunął całą funkcję bądź zmienił jej nazwę) - musiałbym przechodzić po wszystkich listach przeparsowanych symbolów i sprawdzać, czy aby na pewno taka-a-taka funkcja/zmienna/przestrzeń nazw/typ się tam znajduje.

ergo napisał(a)

Trzeba by więc przelecieć wszystkie itemy i zapisać które są rozwinięte.

I tak będziesz musiał przeskanować całe drzewo;

Nie wiem tylko ile czasu zajmuje znalezienie odpowiedniego węzła, a ile ponowne zbudowanie całego drzewa, więc to jest tylko insynuacja; Kodu jeszcze nie widziałem :]

Tak na lagikę biorąc - potrzebujesz zaktualizować kilka węzłów, więc od razu nasuwa się myśl: "Aha, trzeba je znaleźć w drzewie i zmodyfikować lub usunąć"; Ty jednak wolisz:

  1. przeskanować całe drzewo i zapisać stan rozwinięcia wszystkich węzłów (czyli de facto zbudować nowe drzewo zawierające jedynie same stany),
  2. usunąć drzewo,
  3. stworzyć nowe, zaktualizowane drzewo,
  4. przeskanować całe zaktualizowane drzewo i poustawiać stan rozwinięcia
  5. usunąć drzewo tymczasowe
    Trochę dużo roboty jak na tak prostą czynność;

Może to i niezbyt trafne porównanie, ale to wygląda tak, jakbyś zrobił takiego SynEdit z CodeFolding i po każdej zmianie zawartości linii, którą można zwinąć - tworzył na nowo całą strukturę zapisując które kawałki kodu były zwinięte, a które nie i odpowiednio je otwierał/zamykał; Na szczęście działa to zupełnie inaczej;

Na dodatek dochodzi jeszcze fakt, że jeśli zbudujesz dodatkowe tymczasowe drzewo zawierające stan rozwinięcia wszystkich węzłów przed aktualizacją, to po zbudowaniu nowego, zaktualizowanego drzewa, informacje o stanie zwinięcia nieistniejących już węzłów będą dalej w drzewie tymczasowym i dodatkowo trzeba będzie je jakoś odsiać, co jest kolejnym utrudnieniem;

Jeśli znowuż informacje o usuwanych węzłach mają nie trafiać do tymczasowego drzewa, algorytm przeszukujący drzewo skomplikuje się, bo będziesz musiał sprawdzić każdy węzeł czy ma być usunięty, czy nie; To też będzie strata czasu i utrudnienie.

0

Fakt, muszę jeszcze nad tym lepiej pomyśleć ;P

Zatem spróbuję jednak nie tworzyć za każdym razem całego drzewa od nowa, lecz po prostu będę je aktualizował - będzie trochę kodu do napisania :P

1

Rozwiązaniem problemu jest VirtualTreeView - poszukaj tego komponentu i pooglądaj dema - jest tam drzewo, które aktualizuje się z setkami rekordów bez zadyszki w real time.

0

Faktycznie, kompletnie zapomniałem o istnieniu VirtualTreeView :>
Aktualnie już to przeglądam, mam nadzieję, że wreszcie uda mi się również i coś konkretnego napisać ;P


Edit: yay, zaimplementowane! Niepotrzebnie to cały dzień odkładałem robiąc masę innych rzeczy: implementacja całości okazała się banalna, a całość zawarłem w dwustu linijek kodu (całą metodę ofc., a nie tylko samo aktualizowanie :P)

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