Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Virtual String Tree Objekte dynamisch nachladen (https://www.delphipraxis.net/47024-virtual-string-tree-objekte-dynamisch-nachladen.html)

etom291272 5. Jun 2005 11:22


Virtual String Tree Objekte dynamisch nachladen
 
Hallo DpLer

Habe ein kniffliges Problem für euch.

In meiner Dokumentenmanegement Software (zu 100% in Delphi geschrieben [Delphi rules :bounce1: ]) verwende ich häufig die Virtual string Tree Komponente vom Mike Lischke. In einer der Ansichten wird eine komplette Übersicht über den Dokumenteingang dargestellt. Das heist es werden alle Dokumente nach alter die jemals mit dieses System erstellt wurden in diesem Virtual String Tree dargestellt. Dabei wird einfach von einem Sql Server eine View in ein Dataset geladen und vom ersten bis zum letzten durchgelaufen.
Da das System für 500.000 Dokumente ausgelegt ist muss ich die Datensicht entsprechend eingrenzen sonst dauert das laden dieser Liste ewig :kotz:
Zur Zeit löse ich das einfach mit einem einstellbaren Top Statement.

Ich hätte aber gern das am Anfang ca 1000 Doks geladen werden und wenn der Benutzer nach unten scrollt
und bei dieser liste ganz unten angekommen ist weitere 1000 automatisch nachgeladen werden. das heist ich müsste irgendwie erkennen wenn die listview ganz unten ist und der benutzer wieder nach unten scrollen will.

Gibt es da irgend eine Möglichkeit :?: :?: :?:
Bin für jeden Vorschlag dankbar :dp:

alzaimar 5. Jun 2005 11:43

Re: Virtual String Tree Objekte dynamisch nachladen
 
Ich habe das mal gemacht, aber ohne eine Virtual String TreeView. Sonder mit der Normalen.
Ich hatte aber nur ca. 20 Einträge unter der Wurzel. (Level 1)
Jeder Knoten hat ein Dummy-Kind (Ein Child-Knoten mit Node.Tag = 1)
Im OnExpand-Ereignis der TreeView habe ich geschaut, ob die Tag-Eigenschaft des ersten Kind des zu expandierenden Knotens den Wert 1 hat. Wenn ja, wurde der Knoten wohl noch nicht expandiert. Also lade ich die Kinder dieses Knotens.
Jedes Kind des Knotens bekommt ein Dummy-Kind (ein Child-Knoten mit Node.Tag = 1).
Usw. Ich hatte 3 Millionen Datensätze, die so darzustellen waren. Natürlich war das blöd, wenn der anwender alle Knoten geöffnet hat, aber wer macht das schon. Schliesslich hätte er dann alle 300.000 Väter anfassen müssen.

Aber, ich such mir die VirtualStringTree Komponente mal raus, weil ich in meinem aktuellen Projekt 500.000 Knoten in Level 1 habe. Und das nervt.

Lannes 5. Jun 2005 12:32

Re: Virtual String Tree Objekte dynamisch nachladen
 
Hallo,
Zitat:

Zitat von alzaimar
...
Jeder Knoten hat ein Dummy-Kind...

um das "+"-Zeichen im TreeView darzustellen, muss kein Dummy-Kind angelegt werden.
Wenn man TTreeNode.HasChildren auf True setzt wird das "+"-Zeichen dargestellt, auch wenn noch kein untergeordnetes Objekte vorhanden ist.

etom291272 5. Jun 2005 14:04

Re: Virtual String Tree Objekte dynamisch nachladen
 
@alzaimar

vielen dank für deinen Beitrag. das mit dem dynamischen Nachladen der Kinder eines Knotens habe ich ähnlich gelöst. ich lese aus der Db aus ob bei einem entsprechenden Knoten Kinder vorhanden sind wenn ja wird ein dummy child angelegt und im onexpand des Trees die wirklichen Kinder dieses Levels nachgeladen.

Bei meinem Problem allerdings habe ich keine Kinder also auch kein onexpand ereignis weil sich die
ganze Liste eigentlich wie ein stringgrid verhält und sich alles in level 0 abspielt :!: :!: :!:

(hab die vst für diese Lösung anderer Komponenten vorgezogen. wäre ja mit der delphi Listview (war um 500% langsamer) oder mit stringgrid auch gegangen.

alzaimar 5. Jun 2005 14:22

Re: Virtual String Tree Objekte dynamisch nachladen
 
Äch sö: Da habe ich dann ein TStringGrid genommen und einfach dynamisch nachgeladen. Wenn Du mit der MSDE arbeitest, dann setzt Du den Clustered Index auf das Feld, das bei Dir die Ordnung beschreibt. Dann schreibst Du Dir eine Stored Procedure:
SQL-Code:
Create Procedure GetTablePacket @StartID int, @Count int as
select top @Count * From MyTable Where ID >=@StartID
Da die MyTable nach ID sortiert ist (durch den clustered index), spart sich die MSDE den Sortiervorgang und Du kannst ohne jegliche Verzögerungen ziemlich resourcenschonend (auf Serverseite!) durch die Tabelle scrollen.

[edit]
Bei anderen DB musst du einfach schauen, über welchen Index bzw. Feld (AutoInc? Primary Key?) Du am einfachsten sortiert auf die Tabelle zugreifen kannst.
[/edit]

Falls Du ein Budget hast, schau Dir mal die QuantumGrid Suite von Developer Express an. Deren Grid kann mit TDatasets und auch ohne. Wenn man das datensensitiv anpackt kann man dem Teil sagen, das es bitte dynamisch laden soll. Dann kann man zwar einige Gimmicks nicht machen, wie nach Spalten sortieren und live filtern (wie z.B. Access oder Excel), aber ansonsten ist es ziemlich geil. Nebenbei kann man noch direkt Master-Detail Beziehungen einbauen. Dann hat jedes Record einen kleinen Expand-Button. Wenn man den anklickt, öffnet sich unter dem Record die Detail-Tabellen. Das Ding kostet ca. 300 Öcken. (www.devexpress.com) Trialversionen gibts nich, aber ne Demo. Die is ziemlich geil.

@Lannes: Danke für den Tip mit dem HasChildren := True.

etom291272 5. Jun 2005 14:54

Re: Virtual String Tree Objekte dynamisch nachladen
 
hy das mit dem index ist schon klar. Hab eine DokumentID mit der ich leicht die richtigen records bekomme. obwohl ich die stringgrid komponente eigentlich nicht verwenden möchte interessiert es mich doch wie du das mit dem dynamisch nachladen gemacht hast. könntest du das bitte ein wenig genauer beschreiben.

wie gesagt möchte es mit der vst kompo lösen also wenn liste ganz unten ist (auch wenn keine zeile im string tree markiert ist) und der benutzer weiter nach unten scrollt sollen weitere x records nachgeladen werden.

:-D

generic 5. Jun 2005 21:02

Re: Virtual String Tree Objekte dynamisch nachladen
 
wenn du die gesamt anzahl hast füge einfach soviele nodes ein.
im on init oder beim ersten "gettext" für den node lädst du diesen dann.

etom291272 5. Jun 2005 21:14

Re: Virtual String Tree Objekte dynamisch nachladen
 
@generic

Danke für diesen Tipp der hört sich genial an :bounce1: :coder2: :bounce1:

werde das diese woche mal in angriff nehmen und ausprobieren :spin2:

etom291272 5. Jun 2005 21:20

Re: Virtual String Tree Objekte dynamisch nachladen
 
@ generic

habe mal kurz drüber nachgedacht :coder:

wenn ich angenommen im meinem recordset 15.000 dokumente vom sql server erhalte ist es ja kein problem
mit recordcount diese 15000 nodes einzufügen aber

:?: wenn der benutzer nach unten scrollt woher sollen die neuen nodes wissen welches dokument sie laden müssen (muss ja eine reihenfolge haben)

:?: aktiviert der benutzer eine spaltensortierung würden dann ja warscheinlich die leeren nodes sortiert werden oder aber es werden dann alle geladen (das wäre kein problem)

generic 6. Jun 2005 13:34

Re: Virtual String Tree Objekte dynamisch nachladen
 
Liste der Anhänge anzeigen (Anzahl: 1)
im falle einer sortierung würde alle nodes geladen bzw. das node init aufgerufen.
wenn du eine sortierung vorgibts kannst du diese mit dem sql sortieren.
die datenmenge müsste dann "open" bleiben.
in jedem "oninitnode" würde dann aus der datenmenge ein weiter datensatz (row) geladen.

btw. ich bezweifel das ein user jemals mehr als 100 einträge sehen will. mehr sind nicht nutzbar.
du solltest dann mehr mit filtern arbeiten.

btw. ich hab mit delphi und mssql ein dms geschrieben. derzeit sind dort ca. 600000 dokumente drin.
ich hab dir mal einen screen dran gehängt.

alle listen/bäume = vst

[edit]

ach ja, die grundinfos sind in der regeln nicht gross. datum, name, beschreibung usw. ich denke bis ca. 10000 stück kann man die auch immer mit reinladen. die bilder oder was auch immer dann on demand

alzaimar 6. Jun 2005 13:54

Re: Virtual String Tree Objekte dynamisch nachladen
 
Was die Frage nach den 'woher sollen die nodes wissen, welche ID sie nachladen sollen' anbelangt, hatte ich Dir einen Tip gegeben.
Wenn Du einen Block lädst, weisst Du ja die ID des UNTERSTEN Records (ID_low). Beim Laden des nächten Blocks lädst Du einfach die nachsten X Records, deren ID > ID_low. Danach setzt Du ID_low wieder auf die unterste Record.ID usw.

Damit kann man natürlich nicht sofort das 650.000 Dokument aus der Mitte laden. Aber das braucht man auch nicht.
Natürlich kann man dann keine Sortierung mehr machen. Stell Dir vor, deine Anwendung ist im Netz und 100 Leute schauen sich das an und auf einmal drücken alle auf die Spaltenüberschrift zum Sortieren: Alle Clients saugen nun alle 100000 Dokumente... gulp.

Nicht umsonst sind beim QuantumGrid diese Features im 'Gridmode' (also wenn dynamisch nachgeladen wird) ausgeschaltet.

etom291272 6. Jun 2005 15:39

Re: Virtual String Tree Objekte dynamisch nachladen
 
@alzaimar

sorry da hätte ich auch selbst drauf kommen können :? :(

danke für eure tips mir ist auch noch eine idee gekommen. ich könnte beim letzten node ganz unten
einen dummy node mit einem child einfügen mit der Bezeichnung "weitere Dokumente ..." wenn dieser
Knoten erweitert wird im onexpand diesen Knoten löschen den nächsten Block laden und wieder diesen
dummy node einfügen. Bei jedem sortiervorgang wird der dummynode ebenfalls gelöscht und neu ganz unten erstellt. (so habe ich die Anzahl der Doks immer noch unter kontrolle die geladen werden damit mir niemand dieses system abschiesst)

@generic

Hört sich interessant an dein projekt Hast du eine ocr funktionalität integriert wenn ja würden mich nähere infos dazu interessieren. Hab zur Zeit aus Kostengründen noch kein ocr für direkte suche im dokument eingebaut (bewegen sich alle so ab 4000€)

:coder:

alzaimar 6. Jun 2005 16:50

Re: Virtual String Tree Objekte dynamisch nachladen
 
Versuch doch mal die profane, billige, Kassenpatientenlistbox. Die hat eine Property 'Style'. Da gibst Du 'lbVirtual' ein. Alles, was Du jetzt noch brauchst, ist die 'Count' Property auf deine 650000000 zu setzen. Dann schreibst Du das OnData Event: Das gibt Dir einen Index und erwartet im Gegenzug einen String... HA!
Delphi-Quellcode:
procedure TForm1.ListBox1Data(Control: TWinControl; Index: Integer; var Data: String);
begin
  If Not Loaded (Index) Then LoadBlockContaining (Index);
  Data := CachedData (Index);
end;
Die Funktion Loaded (aIndex : Integer) : Boolean prüft, ob der Datensatz #aIndex schon geladen wurde. Bei der Idee mit den Blöcken kann man sich ja merken, wieviele Blöcke schon geladen wurden. Dann reduztiert sich die Funktion auf:
Delphi-Quellcode:
Function Loaded (aIndex : Integer) : Boolean;
Begin
  Result := (aIndex <= NoOfRecsLoaded);
End;
Die Prozedur zum Laden eines Datenblocks sähe ungefähr so aus:
Delphi-Quellcode:
Procedure LoadBlockContaining (aIndex : Integer);
Var
  RecsLoaded : Integer;

Begin
  While NoOfRecsLoaded < aIndex Do Begin
    GetBlock (fLastID, RecsLoaded);
    fLastID := RecordBlock [RecordBlock.count].ID;
    NoOfRecsLoaded := NoOfRecsLoaded + RecsLoaded;
    End;
End;
GetBlock liest also einen Block von 1000 Records, deren ID > fLastID ist, und hängt ihn an deinen Cache an.

Damit deine SW garantiert nicht abschmiert, könntest Du noch dafür sorgen, das in deinem Cache nur die 10000 zuletzt angefassten Records sind. Da bietet sich eine LRU-Liste ("Least recently used" Verkettete Liste) an. Immer wenn auf einen Record zugegriffen wird, kommt der Record an den ANFANG der Liste. Wenn Du dann deinen Cache verkleinern musst, schmeisst Du die Records vom ENDE der Liste raus (denn die sind ja lange nicht angefasst worden).

Wenn du das machst, 'verkomplizieren' sich die o.g. Routinen dezent, aber nicht wirklich tragisch.

generic 6. Jun 2005 20:31

Re: Virtual String Tree Objekte dynamisch nachladen
 
Zitat:

Zitat von etom291272
@alzaimar
Hört sich interessant an dein projekt Hast du eine ocr funktionalität integriert wenn ja würden mich nähere infos dazu interessieren. Hab zur Zeit aus Kostengründen noch kein ocr für direkte suche im dokument eingebaut (bewegen sich alle so ab 4000€)

nicht ganz es gibt eine opensource c lösung.
mein dms braucht aber keine ocr im sinne von texterkennung. ich habe am meisten mit faxen zu tun welche nur 75 dpi haben und da nix leserliches mehr raus kommt. finereader engine hatte zumindest nur eine trefferrate von ca. 5%. deshalb ich nur eine erkennung von 2 dimensionalen strichcodes (wie im beispiel zu sehen).

ansonsten ist mein tipp finereader engine - die ist aber teuer - laesst sich aber leicht von delphi nutzen.
hat imho auch die beste erkennungsrate.

alzaimar 7. Jun 2005 15:25

Re: Virtual String Tree Objekte dynamisch nachladen
 
Nachtrag: eine ListView kennt auch einen 'Virtual Mode'. Nur heisst der OwnerData := True.
Dann noch die Items.Count Property auf die Anzahl der Dokumente setzen und das OnOwnerData überschreiben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz