Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   konzeptionelle Gedanken optische Darstellung Stammbaum (https://www.delphipraxis.net/186117-konzeptionelle-gedanken-optische-darstellung-stammbaum.html)

hansklok 5. Aug 2015 02:34

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:
  • Proband: TTreeItem
  • Children: TObjectList (TTreeItem)
  • Father: TTreeItem
  • Mother: TTreeItem
  • GrandPaA: TTreeItem
  • GrandPaB: TTreeItem
  • GrandMaA: TTreeItem
  • GrandMaB: TreeItem
  • Offset: TBitmap
Später könnten auch noch eine Liste mit den Partnern (Spouses) und Geschwistern (Siblings) hinzugefügt werden. Es geht aber erstmal ums Prinzip.

TTreeItem hat folgende Eigenschaften:
  • ID: Integer
  • Offset: TBitmap
  • Width: Integer = 200
  • Height: Integer = 75

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:
  • gibt es einen Probanden?
  • hat der Proband Eltern? Einen Teil, oder beide (Breite würde sich verdoppeln!)
  • hat der Proband Kinder? (Breite generiert sich dynamisch aus der Anzahl der Kinder + 20 Pixeln Abstand dazwischen)
  • so in etwa, mit den Großeltern wäre es dasselbe, wobei in der 1. Generation da ja maximal 4 TTreeItems nebeneinander stünden

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.

idefix2 5. Aug 2015 06:42

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:
offset: TBitmap
vorhast, versteh ich überhaupt nicht.

bcvs 5. Aug 2015 06:59

AW: konzeptionelle Gedanken optische Darstellung Stammbaum
 
Zitat:

Zitat von hansklok (Beitrag 1311041)
  • Proband: TTreeItem
  • Children: TObjectList (TTreeItem)
  • Father: TTreeItem
  • Mother: TTreeItem
  • GrandPaA: TTreeItem
  • GrandPaB: TTreeItem
  • GrandMaA: TTreeItem
  • GrandMaB: TreeItem
  • Offset: TBitmap

Die Großeltern kannst du dir sparen. GrandPaA ist doch einfach Father.Father

TiGü 5. Aug 2015 08:46

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.

hansklok 5. Aug 2015 12:36

AW: konzeptionelle Gedanken optische Darstellung Stammbaum
 
Zitat:

Zitat von idefix2 (Beitrag 1311053)
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 Daten werden aus einer SQLite-Datenbank geholt, deswegen hat TTreeItem eine ID-Property!
Zitat:

Zitat von TiGü (Beitrag 1311083)
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.

Genau, es geht ja nur um die Darstellung eines Teilbereiches. Gern würde ich alle möglichen Generationen iterativ darstellen, nur handelt es sich bei meinen Vorstellungen um eine Art "Sanduhrdiagramm". Die Darstellung müsste ja immer ausgehend vom Probanden generiert werden. Alles oberhalb hat immer einen Vater und eine Mutter, unterhalb haben alle Einträge 0..* Kinder.
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. :(

Namenloser 5. Aug 2015 13:18

AW: konzeptionelle Gedanken optische Darstellung Stammbaum
 
Zitat:

Zitat von hansklok (Beitrag 1311115)
Genau, es geht ja nur um die Darstellung eines Teilbereiches. Gern würde ich alle möglichen Generationen iterativ darstellen, nur handelt es sich bei meinen Vorstellungen um eine Art "Sanduhrdiagramm". Die Darstellung müsste ja immer ausgehend vom Probanden generiert werden. Alles oberhalb hat immer einen Vater und eine Mutter, unterhalb haben alle Einträge 0..* Kinder.

Und wo ist das Problem?

Ich würde TTreeItem (oder besser TPerson) so definieren:

Delphi-Quellcode:
TPerson = class
  Mother: TPerson;
  Father: TPerson;
  Name: String;
end;
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.

Dann noch TFamilyTree in etwa so:
Delphi-Quellcode:
TFamilyTree = class
  Family: TList<TPerson>;
  function TreeToLayers(Subject: TPerson; Depth: Integer): TList<TLayer>;
end;
Um den Baum (eigentlich ein Graph) zu zeichnen, musst du über den Graphen iterieren und ihn in „Schichten“ (= Generationen) anordnen.
Delphi-Quellcode:
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;
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.

Die Schichten kannst du dann problemlos in einer Richtung zeichnen.

Bentissimo 5. Aug 2015 13:20

AW: konzeptionelle Gedanken optische Darstellung Stammbaum
 
In einem meiner kommerziellen Programme habe ich etwas vergleichbares für Schach, speziell Eröffnungsvarianten, gebaut.

http://project-it.de/horst/images/pr...antenbaum2.gif

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.

idefix2 5. Aug 2015 13:34

AW: konzeptionelle Gedanken optische Darstellung Stammbaum
 
Zitat:

Zitat von hansklok (Beitrag 1311115)
Es get nur darum, dass das ganze Scrollbar sein soll.

Worin besteht das Problem?
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:

Zitat von Namenloser (Beitrag 1311117)
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.

Es kann schon ganz praktisch sein, wenn von jedem Knoten weg in alle Richtungen verkettet wird:
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.

Namenloser 5. Aug 2015 13:39

AW: konzeptionelle Gedanken optische Darstellung Stammbaum
 
Zitat:

Zitat von idefix2 (Beitrag 1311120)
Zitat:

Zitat von Namenloser (Beitrag 1311117)
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.

Es kann schon ganz praktisch sein, wenn von jedem Knoten weg in alle Richtungen verkettet wird:
Person -> Vater
Person -> Mutter
Person -> nächstälteres Geschwister
Person -> nächstjüngeres Geschwister
Person -> jüngstes (oder ältestes) Kind

Redundanz ist in meiner Erfahrung immer schlecht und gilt es so gut es geht zu vermeiden. Man kann sich Methoden bauen, die einem die entsprechenden Familienmitglieder zurückgeben. Aber man sollte sie nicht explizit speichern.

mkinzler 5. Aug 2015 13:44

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 17:41 Uhr.
Seite 1 von 4  1 23     Letzte »    

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