AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Komponente ableiten

Ein Thema von hansklok · begonnen am 30. Aug 2010 · letzter Beitrag vom 1. Jan 2011
Antwort Antwort
Seite 1 von 2  1 2      
hansklok

Registriert seit: 14. Apr 2004
Ort: Karlsruhe
318 Beiträge
 
Delphi 2010 Architect
 
#1

Komponente ableiten

  Alt 30. Aug 2010, 17:42
Hallo,

ich habe eine Komponente "TPerson" erstellt, die von TCustomControl abgeleitet ist. Sie besitzt eine Eigenschaft "Markiert" vom Typ Boolean . Desweiteren habe ich eine Komponente "TStammbaum" erstellt, die ebenfalls von TCustomControl abgeleitet ist. Innehalb dieser habe ich 15 "TPerson"'s erstellt und platziert. Damit ich über den Quelltext eine einzelne "TPerson" ansprechen kann, habe ich zusätzlich noch eine TObjectList "Personen" innerhalb von "TStammbaum" erstellt. Nun möchte ich, dass wenn der Nutzer eine "TPerson" klickt, diese den Status markiert (True) erhält und alle anderen den Status False erhalten. Wenn ich die Komponenten via Quelltext über die Objektliste anspreche funktioniert das auch wunderbar. Sobald ich aber die OnClick Procedure von TStammbaum überschreiben möchte in etwa so procedure TStammbaum.Click(Sender: TObject); weigert sich Delphi zu kompilieren, weil er mit dem Sender nichts anfangen kann. Verwende ich nur procedure TStammbaum.Click; override; funktioniert zwar das Programm aber sobald ich auf eine TPerson klicke, tut sich gar nichts. Aber nur über TSender könnte ich die anderen Komponenten (TPerson) die sich auf TStammbaum befinden mit einer Klick-procedure ansprechen. Hat mich jmd. verstanden und kann mir bitte nen Tipp geben?

Vielen Dank

hansklok
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.867 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Komponente ableiten

  Alt 30. Aug 2010, 17:46
In diesem Fall drafst du nicht Überschreiben, sondern Überladen

procedure TStammbaum.Click(Sender: TObject); overload;
Markus Kinzler
  Mit Zitat antworten Zitat
hansklok

Registriert seit: 14. Apr 2004
Ort: Karlsruhe
318 Beiträge
 
Delphi 2010 Architect
 
#3

AW: Komponente ableiten

  Alt 30. Aug 2010, 17:47
@mkinzler: Danke erstmal, und wie muss ich das Deklarieren?
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#4

AW: Komponente ableiten

  Alt 30. Aug 2010, 17:48
Moin,
abgesehen davon, wäre es nicht sinnvoller zu speichern, welches markiert ist? Dann musst du nicht alle durchgucken um herauszufinden, welches markiert ist.

MfG
Fabian
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
hansklok

Registriert seit: 14. Apr 2004
Ort: Karlsruhe
318 Beiträge
 
Delphi 2010 Architect
 
#5

AW: Komponente ableiten

  Alt 30. Aug 2010, 17:51
@xZise: ...ich speicher den Tag der markierten TPerson in einer Integer-Variable innerhalb von TStammbaum, jedoch muss ich ja dennoch alle anderen TPersons durchlaufen lassen, um deren Markiert auf False zu setzen, oder?

@DaddyH: Wie würde so etwas aussehen? Das erscheint mir logisch.

@mkinzler: Nun löst aber das Click Ereignis überhaupt nicht mehr aus.

Geändert von hansklok (30. Aug 2010 um 18:00 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#6

AW: Komponente ableiten

  Alt 1. Sep 2010, 16:14
@xZise: ...ich speicher den Tag der markierten TPerson in einer Integer-Variable innerhalb von TStammbaum, jedoch muss ich ja dennoch alle anderen TPersons durchlaufen lassen, um deren Markiert auf False zu setzen, oder?[...]
Ich sehe gerade TPerson muss das wissen, um sich zu zeichnen. Aber dennoch musst du nicht alle durchlaufen. Du weißt ja wer markiert war.

Delphi-Quellcode:
type
  TStammBaum = class
  private
    FMarkiert : TPerson; // Statt Integer, so muss man nicht mehr rechnen.
    procedure SetMarkiert(const APerson : TPerson);
  public
    property Markiert : TPerson read FMarkiert write SetMarkiert;
  end;

procedure TStammBaum.SetMarkiert(const APerson : TPerson);
begin
  if Assigned(FMarkiert) then
    FMarkiert.Markiert := False;
  FMarkiert := APerson;
end;
Alternativ könnte die Person den Stammbaum auch fragen ob es markiert ist (z.B. mithilfe eines Events) aber ich denke diese Lösungs ist wohl besser.

MfG
Fabian
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
r2c2

Registriert seit: 9. Mai 2005
Ort: Nordbaden
925 Beiträge
 
#7

AW: Komponente ableiten

  Alt 1. Sep 2010, 21:16
So, hier ist mal ein Grundgerüst. Die Arbeit von heute Nachmittag....

Es ist ausdrücklich nicht vollständig. Kleinkram hab ich weggelassen. z.B. hab ich zu den Personen nicht noch Eigenschaften wie Geschlecht oder Namenszusätze spezifiziert. Für die Idee sind die erstmal egal. Du kannst die dann selbst ergänzen.

Die Diagramme hab ich mit dem SoftwareIdeasModeler (www.softwareideas.net) gemacht. Das Prog läuft auch unter nem aktuellen Mono, was für mich als Linuxer recht praktisch ist. Das Programm hat zwar auch seine Macken (z.B. lassen sich zumindest unter Linux reflexive Assoziationen nicht so richtig positionieren), aber es ist benutzbar. Das Projekt ist im Anhang. Kannst du dir angucken.

Die Klassendiagramme sollten eigentlich recht selbsterklärend sein. Ich hab versucht sie möglichst einfach zu halten. Wenn dir die Dinger nicht so geläufig sind, guck einfach mal in die Wikipedia. Die Grundidee ist eigentlich ganz einfach.

So, dann legen wir mal los:

Zuerst einmal bauen wir uns ein Domänenmodell. Wir bauen also einfach die relevanten Teile der Wirklichkeit nach.

- Es gibt Personen und die sind irgendwie miteinander verwandt.
- Interessant ist nun wie man miteinander verwandt sein kann. Wär ja zu einfach, wenns da nur Mutter-Vater-Kind gäbe. Also, was gibts denn da für Sonderfälle?
* Verwitwet und später nochmal geheiratet ==> Das sind zwei getrennte Familien
* Geschieden und später nochmal geheiratet ==> dito
* Annulierte/für nichtig befundene Ehen ==> haben nie existiert; werden behandelt wie uneheliche Partnerschaften
* Uneheliche Kinder/Seitensprünge ==> Das wird schon lustiger. Ne Familie is sowas ja wohl nicht. Sollte man wohl ne eigene Klasse dafür machen.
* Ungeklärte Vaterschaften ==> solche Kinder könnte man zur vermuteten/vorgeblichen/wasauchimmer Familie packen und ne Notiz drankleben. Oder man erstellt dafür ne Familie mit unbekanntem Vater. Hierzu könnte man Dummy-Objekte oder nil-Werte speichern. Oder man führt ne neue Klasse ein.
* Ungeklärte Mutterschaften sind vermutlich seltener, könnte es aber auch geben; manche Daten lassen sich historisch vllt. einfach nicht mehr rekonstruieren ==> wie ungeklärte Vaterschaften
* Künstliche Befruchtung und Austragen durch eine Leihmutter. ==> Äh... hm... Das wird wohl ein zusätzliches Attribut
* Inzest ==> Keine Familie aber dennoch eine "Verbindung"
* Adoptionen ==> Hmm... ein Adoptivkind hat biologische Eltern und Adoptiveltern. Zudem könnte es auch sein, dass unverheiratete Einzelpersonen Kinder adoptieren. Ne Adoption ist demnach wohl was separates, gibt also ne eigene Klasse.
* Achso: Und man könnte mehrmals von unterschiedlichen Leuten adoptiert worden sein.

Hab ich jetzt alle möglichen und unmöglichen Fälle?

Aber zumindest ist eins sicher: Jeder Mensch hat nen Vater und ne Mutter - mögen sie bekannt sein oder nicht. Da ist wohl kaum dran zu rütteln. Deshalb kriegt TPerson je eine Referenz auf nen Vater und auf ne Mutter.

Bei solchen Objektgeflechten hat man zwei Möglichkeiten: Jede Info nur einmal (DRY principle) speichern und dadurch Redundanzen vermeiden oder das Objektgeflecht leichter navigierbar machen, dann aber eine hohe Zahl von Invarianten in Kauf nehmen. Beides hat seine Vor- und Nachteile. Hier, würde ich sagen, müssen wir leider das DRY-Prinzip etwas verletzen, damit wir leichter navigieren können. Also beispielsweise nicht nur von den Kindern zu den Eltern, sondern auch umgekehrt.

Nächster Schritt: Was haben wir an unterschiedlichen "Verbindungen"? Ehe, uneheliche Partnerschaft, Seitensprünge, Inzestfälle, teilweise ungeklärte Fälle, ... Wir könnten das in eine Klasse packen und einen Typ mit speichern oder für jedes eine eigene Klasse nehmen. Zumindest aber Ehen haben zusätzliche Attribute: Ein Datum der Eheschließung; ein Datum der Scheidung (durch Tod, Gerichtsbeschluss oder wie auch immer das gehen mag); wenn du die auch noch erwähnen willst: Trauzeugen, u.ä. ==> Am einfachsten ist, wir unterscheiden Ehen und sonstige Partnerschaften.

Ich hab zwar von Genealogie keine Ahnung, aber teilweise kann es wohl sein, dass es Daten gibt, die einfach unbekannt sind. Oder nur ungefähr bekannt "muss vor 1350 gestorben sein", "geboren um 1720", etc. Deshalb bauen wir uns eine Klasse bzw. hier einen Record, der mit sowas umgehen kann. TVagueDate. Durch überladene Operatoren kann man sowas dann fast benutzen wie ein normales TDate. Solltest du ne ältere Delphi-Version ahben, die noch keine Operatorenüberladung gestattet, musst du dafür eben Funktionen schreiben.

Jetzt haben wir ein Domänenmodell. Das tut aber bisher noch nix. Jetzt brauchen wir Operationen, die das Objektgefecht aufbauen und verändern. Dabei tun das die Objekte selbst. Es wird nicht von außen etwas gebaut und dann an den Objekten geändert, beispielsweise eine marriedTo-Eigenschaft gesetzt. Das wäre nicht objektorientiert. Stattdessen machen die Tperson-Objekte genau das, was reale Personen auch tun. Sie heiraten. Also gibt es eine Methode marry(TPerson) . Das Prinzip nennt sich "Tell, don't ask!" oder "Do ist myself"-Prinzip. Die Objekte werden nicht von außen geändert, sondern sie machen alles selbst.

In deiner kleinen Modellwelt machen die Personen also alles genau so, wie echte Menschen:
Delphi-Quellcode:
// Pseudocode
var
  Alice, Bob: TPerson;
  Charlie, Doris: TPerson;
  Peter: TPerson;

...
  
Alice.marry(Bob, Now);
Charlie := Alice.giveBirthToChildFrom(Bob, Now);
Doris := Alice.giveBirthToChildFrom(Bob, Now);
Bob.die(Now);
Alice.marry(Peter, Now);
Alice.die(Now);
Und genau das ist es, was die OO so toll macht. Man kriegt sehr schönen lesbaren Code. Den Code oben kannst du jemandem zeigen, der von Programmierung keine Ahnung hat und mit n bisschen Überlegen wird er ihn trotzdem verstehen. Und auch du wirst das besser verstehen, weil sich der Code im Idealfall (und das Beispiel oben ist ziemlich nah dran an diesem Idealfall) liest wie ein englischer Text.

Tell, don't ask sieht man hier ganz deutlich: Alice.marry(Bob, Now); "Alice, marry Bob now!" Wir sagen Alice, was sie zu tun hat und die wird das auch pflichbewusst tun. Prozedural würde das so aussehen:
Delphi-Quellcode:
// vereinfacht
Alice.marriedTo := Bob;
Alice.marriageDate := Now;
Bob.marriedTo := Alice;
Bon.marriageDate := Now;
Eigentlich würde das noch nichtmal reichen. Was, wenn Bob bereits verheiratet ist? Also müssten weitere Abfragen rein. Und das außerhalb von TPerson. Aber eigentlich sollten die Personen doch selbst wissen, wie man heiratet. Deshalb gehört der Code in TPerson rein und die Personen tun alles, was zum Heiraten nötig ist, selbst.

Wie würde TPerson.marry() nun aussehen? In etwa folgendermaßen:
Delphi-Quellcode:
// Pseudocode; gerade bei dem ganzen Moglichkeits-Gedöns müsste man nochmal drüber gucken

const
  MAX_AGE = 150; // it is supposed that there are no older people
  UNCERTAINTY = 200; // if a date is marked uncertain, it is uncertain w.r.t. this number of years in the one or the other direction

function TPerson.marry(AOtherPerson: TPerson; ADate: TVagueDate): TMarriage;
var
  Exception: EMarriageImpossibleException;
begin
  assert(AOtherPerson <> nil);
  
  //////////// first handle error cases ////////////////////////////////////
  
  // prevent overlapping marriages:
  if not (ADate.isUnknown or ADate.isUncertain) then
  begin
    for m: TMarriage in Self.Marriages do
    begin
      if (m.Start < ADate) and (m.End > ADate) then
      begin
        Exception := EMarriageImpossibleException.Create('Overlapping marriage');
        Exception.ConflictingMarriage := m;
        raise Exception;
      end;
    end;
    for m: TMarriage in AOtherPerson.Marriages do
    begin
      if (m.Start < ADate) and (m.End > ADate) then
      begin
        Exception := EMarriageImpossibleException.Create('Overlapping marriage');
        Exception.ConflictingMarriage := m;
        raise Exception;
      end;
    end;
  end
  else
  begin
    // do nothing
    // do not prevent marriage, if end of other marriage is uncertain or unknown
  end;
  
  // prevent marriage of probably dead people
  if Self.isProbablyDead(ADate) or AOtherPerson.isProbablyDead(ADate) then
  begin
    raise EMarriageImpossible.Create('Dead people cannot be married.');
  end;
  
  // prevent marriage of people probably not born yet
  if Self.hasProbablyBeenBorn(ADate) or AOtherPerson.hasProbablyBeenBorn(ADate) then
  begin
    raise EMarriageImpossible.Create('People have to be born before they can marry.');
  end;
  
  
  //////////// error cases handled, now do the actual work /////////////////
  
  Result := TMarriage.Create();
  
  // if there is already a partnership convert partnership to marriage:
  for p: TPartnershup in Self.Partnerships do
  begin
    // partnership with this person
    if ((p.Mother = Self) and (p.Father = AOtherPerson))
      or ((p.Father = Self) and (p.Mother = AOtherPerson)) then
    begin
      if not (p is TMarriage) then
      begin
        Result.Assign(p); // copy values
        p.Free; // can be freed here because all references to it will be replaced
        break; // there can be only one partnership
      end
      else
      begin
        // this cound be ether a former marriage with is person which has been devorced
        // or an overlapping marriage; The overlapping marriage is prevented above
      end;
    end;
  end;

  // set values
  Result.Start := ADate;
  
  // homosexual marriages leads to random assignment to Father and Mother
  // this is no problem as they won't get own children and adoptation
  // is treated separately
  if Self.isFeamle then
  begin
    Result.Mother := Self;
    Result.Father := AOtherPerson;
  end
  else
  begin
    Result.Mother := AOtherPerson;
    Result.Father := Self;
  end;
  
  Self.Partnerships.Add(Result);
  AOtherPerson.Partnerships.Add(Result);
  
  assert(Result <> nil);
  assert(Self.Partnerships.Contains(Result));
  assert(AOtherPerson.Partnerships.Contains(Result));
end;

function TPerson.isDead(ADate: TVagueDate): Boolean;
begin
  Result := ADate > Self.DateOfDeath;
  // overloaded operator '>' takes care that this is only true when the date is certain
end;

function TPerson.isProbablyDead(ADate: TVagueDate): Boolean;
begin
  Result := isDead or (age > MAX_AGE) or (probableAge > (MAX_AGE + UNCERTAINTY));
end;
Genau so geht es mit divorce(), die(), giveBirthToChildFrom(), ...

Zusätzlich zu den offensichtlichen Methoden gibt es noch ein paar weitere. Personen können nämlich nicht nur Kinder kriegen, sondern auch Eltern. Also natürlich nicht "Guck ma, ich hab heut ne Mama gekriegt!", sondern dadurch, dass man Ahnenforschung betreibt und so neue Namen erfährt. Das muss natürlich auch noch rein. Über addParents z.B. kann man eine bestehende Partnerschaft als Eltern einfügen. addMother würde eine neue Partnerschaft erzeugen, die Mutter-Rolle spezifizieren, den Vater erstmal undefiniert lassen und die neue Partnerschaft als Eltern der Person eintragen. addFather ebenfalls. Wenn addFather ausgeführt wird, wenn schon ne halbe Partnerschaft da ist (Mutter bekannt, Vater noch nicht), wird natürlich die bestehende Partnerschaft genutzt. Und wenn der Vater bereits bekannt ist, aber trotzdem addFather aufgerufen wird, ist wohl was faul ==> Exception

Prinzip verstanden?

Ein weiterer Punkt noch:
Wie oben erwähnt, gibt es diverse Invarianten also Bedingungen, die immer gelten müssen, damit die Daten konsistent sind:
- Eine Person kann nicht gleichzeitig Vater und Mutter sein.
- Im Stammbaum darf es keine Zyklen geben, d.h. keiner kann sein eigener Vater sein.
- Es können nur Personen heiraten, die auch gleichzeitig leben.
- Kinder können nicht älter als ihre Eltern sein.
- Die Kinder, die in TPartnership aufgeführt sind müssen auch diese Partnership als Eltern angegeben haben
- ...

Auf diese Invarianten musst du besonders aufpassen. Wenn sich einmal Kinder und Eltern nicht mehr einig darüber sind, wer nun wen geboren hat, gibts furchtbaren Streit und du hast wunderbare Bugs, die du jagen darfst. Werfe also entsprechende Exceptions. Zudem gibt es Programmierfehler, die du über Assertions abfangen kannst. Oft sind das nil-Werte. Wenn du mal irgendwo ein nil stehen hast, wo keines hin gehört, wirds auch lustig. Also auch hier aufpassen.

Ich hatte dich ja gewarnt, dass es viel Arbeit sein wird. Hier kommt sie nämlich:

Folgendes solltest du jetzt tun:
- verstehen, was ich geschrieben habe
- bei Unklarheiten nachfragen
- meine Idee verstehen
- bei Unklarheiten nachfragen
- gucken, ob das fachlich passt. Ich hab von Genealogie nicht wirklich Ahnung. Vielleicht hab ich ja einen fachlichen Kapitalfehler gemacht.
- überlegen, ob du Adoptionen berücksichtigen willst; die kann man beispielsweise auch gut vorerst mal ausklammern und später einbauen
- überlegen, ob das mit TVagueDate nötig/sinnvoll/kontraproduktiv/wasauchimmer ist
- ggf. logische Fehler in meinem Ansatz finden

Dann solltest du
- weitere Invarianten finden und dokumentieren
- das Diagramm um wichtige weitere Operationen und Attribute ergänzen; verlieb dich da nicht allzu sehr ins Detail; das kostet nur Zeit. Also nicht jetzt Namenszusätze und anderen unwichtigen Kleinkram spezifizieren, sondern das, was wirklich gebraucht wird.
- mir das Ergebnis zeigen

Wenn du willst, kannst du probehalber auch schon was implementieren. Es kann nur sein, dass sich da noch was ändert.

Die dann folgenden Schritte wären:
- Speichern und Laden modellieren; dazu gibts wohl separate Klassen
- Die grafischen Repräsentationen, die den Stammbaum darstellen, modellieren
- Das Ganze auch implementieren und testen
- Jetzt den Kleinkram dazu


//Nachtrag: Ich sehe gerade: Die Grafik hat tansparenten Hintergrund und das Forum wählt Schwarz statt weiß als Default. ==> einfach auf der Platte speichern und so ansehen...

mfg

Christian
Angehängte Grafiken
Dateityp: png Genealogie.png (108,6 KB, 43x aufgerufen)
Angehängte Dateien
Dateityp: zip Genealogie.zip (4,3 KB, 17x aufgerufen)
Kaum macht man's richtig, schon klappts!

Geändert von r2c2 ( 1. Sep 2010 um 21:20 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.655 Beiträge
 
Delphi 12 Athens
 
#8

AW: Komponente ableiten

  Alt 30. Aug 2010, 17:50
Das Click-Ereignis tritt doch erst einmal bei den Personen ein, oder habe ich Dich falsch verstanden? Dann könntest Du doch ein Event OnPersonClick in TStammbaum einführen. Die TPersonen leiten Klicks dann an dieses Event weiter. Das ist leider etwas unelegant, weil die Personen dann den Stammbaum kennen müssen, aber mit etwas Überlegung lässt sich das bestimmt auch noch umgehen.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
r2c2

Registriert seit: 9. Mai 2005
Ort: Nordbaden
925 Beiträge
 
#9

AW: Komponente ableiten

  Alt 30. Aug 2010, 18:54
Hier läuft was schief. Im Ansatz schon.

ich habe eine Komponente "TPerson" erstellt, die von TCustomControl abgeleitet ist.
OK soweit. Auch, wenn man sich darüber streiten kann, inwieweit es nicht besser wäre, hier Darstellung und Logik mehr zu trennen.

Zitat:
Sie besitzt eine Eigenschaft "Markiert" vom Typ Boolean .
Das ist schon fragwürdig. Muss die Person das wirklich wissen oder ist das eher eine Eigenschaft des Stammbaums. Beides könnte der Fall sein. Kommt drauf an, wie der restliche Ansatz aussieht.

Zitat:
Innehalb dieser habe ich 15 "TPerson"'s erstellt
Innerhalb? Kommt mir komisch vor...

Zitat:
und platziert. Damit ich über den Quelltext eine einzelne "TPerson" ansprechen kann, habe ich zusätzlich noch eine TObjectList "Personen" innerhalb von "TStammbaum" erstellt.
Hm... kann ne gute Idee sein. Wenn du weißt, was du tust.

Zitat:
Nun möchte ich, dass wenn der Nutzer eine "TPerson" klickt, diese den Status markiert (True) erhält und alle anderen den Status False erhalten.
Das macht mich glauben, dass die Markierung eher eine Eigenschaft des Stammbaums ist.

Zitat:
Wenn ich die Komponenten via Quelltext über die Objektliste anspreche funktioniert das auch wunderbar. Sobald ich aber die OnClick Procedure von TStammbaum überschreiben möchte in etwa so procedure TStammbaum.Click(Sender: TObject); weigert sich Delphi zu kompilieren, weil er mit dem Sender nichts anfangen kann.
Das ist klar. Click hat ja auch keine Parameter. Aus gutem Grund.

Zitat:
Verwende ich nur procedure TStammbaum.Click; override; funktioniert zwar das Programm aber sobald ich auf eine TPerson klicke, tut sich gar nichts.
Klar. Weil eine Person etwas anderes ist als der Stammbaum.

Vorschlag: Du erklärst mal genauer, was du vor hast. Und zwar wirklich was und nicht wie. Dann machen wir uns mal gemeinsam Gedanken darüber, wie man das besser machen könnte...

mfg

Christian
Kaum macht man's richtig, schon klappts!
  Mit Zitat antworten Zitat
hansklok

Registriert seit: 14. Apr 2004
Ort: Karlsruhe
318 Beiträge
 
Delphi 2010 Architect
 
#10

AW: Komponente ableiten

  Alt 30. Aug 2010, 21:03
Im Grunde genommen geht es um die Erstellung eines Programms zur Speicherung Genealogischer Inhalte (Familienforschung). Im Control sollen je nach Auswahl des Users 2 bis 4 Generationen angezeigt werden.
Es gibt eine Klasse, die Personendatensätze. Eine Person können Eltern, Geschwister, Partner hinzugefügt werden. Die jeweils ausgewählte Person soll als Proband (1. Generation) im Stammbaum erscheinen, dahinter Vater und Mutter (2. Generation), dann Großvater und Großmutter (väterlicherseits) und umgekehrt (mütterlicherseits) (3. Generation) usw. Wird z.B. auf den Vater geklickt, so soll dieser Markiert werden und ein Editiermodus starten. Wird er doppelt geklickt, so soll er zum Probanden werden, also an die Position 1 (1. Generation) rutschen, dem entsprechend ändern sich auch die anderen Namen in der 2. bis 4. Generation in der Stammbaumansicht.

Gruß hansklok
Angehängte Grafiken
Dateityp: png stammbaum.png (19,9 KB, 45x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:57 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