![]() |
konzeptionelle Gedanken optische Darstellung Stammbaum
Ein herzliches Hallo an alle,
Ich würde gern einen Stammbaum grafisch und interaktiv ausgeben. Jedes Element soll anklickbar sein. Ich dachte mir, dass ich dazu zwei Klassen brauche: TFamilyTree (abgeleitet von TCanvas) und TTreeItem. TFamilyTree hat folgende Eigenschaften, da ich bis zu 4 Generationen (optional) abbilden möchte:
TTreeItem hat folgende Eigenschaften:
Nun soll TFamilyTree beispielsweise nie größer als 800x600 Pixel sein. Die Größe des Offsets soll sich dynamisch generieren. Dazu muss folgendes gecheckt werden:
Hat ein Proband nun sehr viele Kinder, wir das Offset schnell breiter, als 800 Pixel. Mich würde nun interessieren, wie man möglichst sinnvoll und WIE die Breite und Höhe des Offsets vorab berechnen kann und wie man bei einer festen Breite und Höhe von TFamilyTree diesen via Scrollbars scrollen kann, aber so, dass man die Objekte immer noch richtig anklicken kann (also eine Koordinatenfrage!). Hat jemand etwas ähnliches schon einmal versucht? Könnt ihr mir folgen? Habe ich mir die richtigen Gedanken gemacht? Danke Euch im Voraus. |
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
Meines Erachtens ist der Ansatz grundlegend falsch. Du vermengst hier die Datenhaltung und die Bildschirmdarstellung.
Die Daten selbst sollten völlig I/O-unabhängig gespeichert werden, und für die Darstellung eines Knotens am Bildschirm definierst du ein TFrame. Die Frames erzeugst du dynamisch nach Bedarf. Anklickbar sind die ganz von selbst, wenn sie einen scrollbaren Container als Parent haben (die Form selbst oder eine Scrollbox auf der Form), da brauchst du nichts selbst zu programmieren. Übrigens: Was du mit
Delphi-Quellcode:
vorhast, versteh ich überhaupt nicht.
offset: TBitmap
|
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
Zitat:
|
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
Ich denke auch, dass du da den falschen Ansatz wählst.
Wenn überhaupt, wird ein Teilbereiches des Baumes auf einen Canvas gemalt (ggf. über eine dritte Klasse), aber sollte sich nicht selber zeichnen, indem es von Canvas abgeleitet ist. Warum eigentlich diese Beschränkung auf 800 x 600 Pixel in der Ausgabe? Um mir Ideen zu holen, würde ich immer bei den großen Playern schauen, wie die bestimmte Sachen lösen. Kennst du myheritage.com? Deren Clientsoftware ist zwar etwas altbacken, aber die Darstellung eines Stammbaumes in der Web-Darstellung finde ich sehr gelungen. |
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
Zitat:
Zitat:
Natürlich kenne ich MyHeritage :wink: Von welcher dritten Klasse sprichst Du? Die Beschränkung war ein Beispiel. Es get nur darum, dass das ganze Scrollbar sein soll. Ich bin für Input weiterhin sehr dankbar, weil es zum Beispiel auch darum gehen wird, wie man dann die einzelnen Verbindungsknoten unter den Einträgen zeichnet etc. Äußerst komplex. :( |
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
Zitat:
Ich würde TTreeItem (oder besser TPerson) so definieren:
Delphi-Quellcode:
Und mehr brauchst du gar nicht. Die Kinder musst du gar nicht speichern, weil sie sich implizit ergeben: Das sind die Personen, wo entweder Father oder Mother das jeweilige Subjekt sind.
TPerson = class
Mother: TPerson; Father: TPerson; Name: String; end; Dann noch TFamilyTree in etwa so:
Delphi-Quellcode:
Um den Baum (eigentlich ein Graph) zu zeichnen, musst du über den Graphen iterieren und ihn in „Schichten“ (= Generationen) anordnen.
TFamilyTree = class
Family: TList<TPerson>; function TreeToLayers(Subject: TPerson; Depth: Integer): TList<TLayer>; end;
Delphi-Quellcode:
In dem Beispielcode werden nur die Ahnen berücksichtigt, aber es ist nicht schwer es so zu erweitern, dass auch Kinder, Geschwichter, Cousins etc. in die jeweiligen Schichten eingefügt werden. Man muss dann nur aufpassen, dass man einen Knoten nicht mehrfach hinzufügt.
type
TLayer = TList<TPerson>; function TFamilyTree.TreeToLayers(Subject: TPerson; Depth: Integer): TList<TLayer>; procedure AssignPerson(Person: TPerson; Layers: TList<TLayer>; LayerIndex: Integer); begin if LayerIndex >= Layers.Count then exit; Layers[CurrentLayerIndex].Add(Person); AssignPerson(Person.Mother, Layers, LayerIndex+1); AssignPerson(Person.Father, Layers, LayerIndex+1); end; var i: Integer; begin Result := TList<TLayer>.Create; for i := 0 to Depth-1 do Result.Add(TLayer.Create); AssignPerson(Subject, 0); end; Die Schichten kannst du dann problemlos in einer Richtung zeichnen. |
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
In einem meiner kommerziellen Programme habe ich etwas vergleichbares für Schach, speziell Eröffnungsvarianten, gebaut.
![]() Dafür habe ich das TdxOrgChart von DexExpress verwendet. Diese Komponente bietet eigentlich alles, was Du für Deine Anforderung benötigst und natürlich gibt es auch eine datenbasierte Variante. Nachteil ist aber natürlich der nicht unerhebliche Kostenfaktor, da es das TdxOrgChart nur als Teil der VCL Subscription gibt. |
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
Zitat:
Für die Darstellung der einzelnen Knoten nimmst du geeignete visuelle Komponenten. Die Komponenten wissen auch, wenn sie gescrollt werden, wann sie angeklickt werden, und du kannst in den entsprechenden Ereignisroutinen (onclick etc.) darauf reagieren. Um das Scrollen brauchst du dich nicht zu kümmern. Die Bildschirmdarstellung sollte ausser der Bildschirmdarstellung nichts tun, insbesonders keine Strukturdaten enthalten. Auf Grund der Strukturdaten, die du in eigenen Klassen bereit hältst, die mit der Darstellung am Schirm gar nichts zu tun haben, erstellst du dann die visuellen Komponenten. Also nicht: Visuelle Komponente enthält Referenz auf Datenbankwert sondern - Aus der Datenbank erzeuge Baum bzw. Netzstruktur, und dann erzeuge für jeden Netzknoten adäquate visuelle Controls mit geeigneten Namen. Wenn ein Control angeklickt wurde, weisst du auf Grund des Parameters "Sender" in allen Ereignisbehandlungsroutinen, wer angeklickt wurde. Zitat:
Person -> Vater Person -> Mutter Person -> nächstälteres Geschwister Person -> nächstjüngeres Geschwister Person -> jüngstes (oder ältestes) Kind edit Wobei das mit den Geschwistern komplizierter ist, es gibt ja auch Halbgeschwister und dergleichen. Da ist es vielleicht wirklich am besten, wie Namenloser schreibt, nur die Eltern zu speichern und für alles andere die Liste aller Personen durchzugehen. So viele Leute können das nicht sein, dass da Performance Probleme drohen würden. |
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
Zitat:
|
AW: konzeptionelle Gedanken optische Darstellung Stammbaum
In einer modernen Welt könnte man auch Father/Mother durch SPouse1/Spouse2 ersetzten oder noch besser die Eltereigenschaft getrennt setzen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:21 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 by Thomas Breitkreuz