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 Suche Pfeile zur Visualisierung von Beziehungen (https://www.delphipraxis.net/97674-suche-pfeile-zur-visualisierung-von-beziehungen.html)

torud 14. Aug 2007 12:21


Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo Wissende,

ich habe ein kleines Tool, mit dem sich XP-Buttons oder ähnliche Inhaltsträger erstellen kann, um Gruppen anzulegen. Diese werden dann einfach mit der Caption befüllt und so verschoben wie man sich die Struktur eines Unternehmens o.ä. vorstellt. Um diese nun noch in Beziehungen zu bringen suche ich noch eine Komponente, die mir verschiedene Pfeile bietet, die zumindest einige Anpassungen ermöglicht, wie z-b.:

Farbe,
Grösse,
Drehwinkel,
Pfeilgrösse und
Dicke...

Irgendwie konnte ich nicht wirklich was finden. Das was ich bei Torry gefunden habe, war nicht Live-Tauglich, also nicht z.b. nicht drehbar. Wenn man die Pfeile an die Buttons oder andere Controls andocken könnte wäre das auch cool.

RavenIV 14. Aug 2007 12:53

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Wenn's was kosten darf:
ExpressOrgChart Suite
$129.99 with full source code, $89.99 without full source code

http://www.devexpress.com/Products/V...hart/Index.xml

torud 14. Aug 2007 13:34

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Danke für Deinen Tipp! Leider war das nicht das, was ich suche, da die nur das bieten, was ich schon habe. Ich brauche einfach nur die Pfeile, um die Beziehungen selbst dazwischen herstellen zu können. Ich könnte das zwar auch mit tranparenten PNG-Pfeilen machen, aber dann kann der Kunde nicht FREI drehen, sondern muss das Bild über eine Trackbar ändern. Das ist ziemlich umständlich und dauert manchmal auch zu lange...

Gibt es noch andere Möglichkeiten?

Ghostwalker 14. Aug 2007 13:46

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Spontan würd ich sagen, selber zeichnen :) Das sollte nicht zu schwer sein. Du brauchst lediglich eine Zeichenfläche (dürfte das Fenster sein auf dem die Buttons sind), sowie anfangs und endpunkte.

torud 14. Aug 2007 14:07

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Ok, da ich da noch nicht ganz durchsteige füge ich mal noch folgende Infos hinzu. Die Buttons, Panels und Gradients sind alles TControls, die auf einer TScrollbox platziert werden und live verschoben werden können. Ich brauche also einen oder mehrer Pfeile, welche ich dieser Scrollbox hinzufügen kann, die möglich auch von TControl kommen, damit ich diese auch ansprechen, verschieben und zur Laufzeit noch drehen und sonstwie ändern kann.

Wie könnte also Dein Ansatz da funktionieren?

Ghostwalker 14. Aug 2007 16:37

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Als Ansatz würde sich da TGraphicsControl anbieten. Zwei Punktkoordinaten für Anfangs- und Endpunkt als zusätzliche Propertys. und dann auf den Canvas entsprechend Pinseln. Die Position und Höhe und Breite haste automatisch mit dabei.

torud 14. Aug 2007 18:22

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hört sich gut an und liest sinnvoll, aber ich damit noch 0-Erfahrung und in diesem Forum waren NUR 5 Threads zum Thema TGraphicsControl zu finden. Naja, da werde ich wohl noch etwas googlen müssen. Ich hoffe nur, dass ich den gezeichneten Pfeil noch anklicken und verschieben kann!?

oki 14. Aug 2007 19:37

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,

ich hatte aktuell ein ähnliches Problem. Meine Verbinder sollen zwar nicht schräg laufen, dafür aber mehrere Ecken haben. Ich hab es mit TGraphicControl probiert. Dann auf TCustomControl geändert. Hier meine Erfahrungen:

TGraphicControl:
Vorteile:
- Hintergrund ist schon transparent,
Nachteile:
- kein Focus
- Größenänderung nicht mit Perform machbar
- nicht durchklickbar

TCustomControl:
Vorteile:
- alle meine anderen Visuellen Elemente sind von TCustomControl abgeleitet (gemeinsamme Basisklasse für Grundfunktionen Selektieren Größe ändern ...)
- Fokus kann gewechselt werden (DoEnter, DoExit)
Nachteile:
- Hintergrund nicht transparent
- nicht durchklickbar


Gelöst habe ich die Themen:
- Größenänderung machbar
- durchklickbar


Bsp.:
siehe Anhang

torud 15. Aug 2007 08:26

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo,

das sieht schon eher nach dem aus, was ich suche. Also ich will ehrlich sein. Ich habe keine Ahnung, wie Du das realisiert hast, aber könntest du mir ein kleinen Happen zum Frühstück reichen? Nicht alles, einfach nur einen Anfang, da ich wirklich nicht weiss, wie es losgehen soll.

Ich suche hier mal im Forum weiter danach, vielleicht finde ich ja was passendes...

oki 15. Aug 2007 11:08

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Liste der Anhänge anzeigen (Anzahl: 3)
Hi torud!

Mein ansatz war folgender.

Ich benötige mehrere unterschiedliche Komponenten, die zur Laufzeit in einer ScrollBox erstellt und bearbeitet werden können. Dazu zählen verschiedenste Komponenten für spezielle Zwecke. Unter anderem sollen diese Elemente in Gruppenboxen angeordnet sein. Im Bild ist zum Bsp. Mein Label mit den entsprechenden Verbindern in einer Gruppenbox zu sehen. Damit ich von "außen" (Hauptprogramm) alle einheitlich suchen oder ansprechen kann, hab ich mir eine Basisklasse geschrieben, in der meine Grundfunktionen enthalten sind.

Delphi-Quellcode:
  TBaseCustomControl = class(TCustomControl)
  private
    FCaption: String;
    FMoveable: Boolean;                // Control verschiebbar
    FOnItemSelected: TNotifyEvent;
    FSelected: Boolean;                 // Control selectiert
    FShowMode: TSeyShowMode;            // Anzeige für Programm-/Designdarstellung
    procedure SetCaption(const Value: String);
    procedure SetSelected(const Value: Boolean);
  protected
    procedure CreateWnd; override;
    procedure DoEnter; override;
    procedure DoExit; override;
    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
    procedure Paint; override;
    procedure SetFirstName;
    procedure SetName(const Value: TComponentName); override;
    procedure SetShowMode(const Value: TSeyShowMode); virtual;
  public
    Constructor Create(AOwner: TComponent); override;

    property Caption : String read FCaption write SetCaption;
    property Color;
    property Font;
    property Moveable : Boolean read FMoveable write FMoveable;
    property OnItemSelected : TNotifyEvent read FOnItemSelected write FOnItemSelected;
    property Selected : Boolean read FSelected write SetSelected;
    property ShowMode : TSeyShowMode read FShowMode write SetShowMode;
  published
    procedure DoItemSelected(Sender : TObject); virtual;
  end;
Von dieser Basisklasse leite ich dann meine weiteren Controls ab. Ein wesentlicher Unterschied zwischen meinen Connectoren und den anderen Elementen (z.B. Label) ist, dass der Connector über die Eckpunkte in seiner Größe verändert wird. Eckpunkt greifen und verschieben. Zwischen zwei Eckpunkten gibt es z.B. horizontale und vertikale Zugpunkte um die entsprechende Teillinie mit ihren Eckpunkten zu verschieben. Da hab ich recht lange dran gesessen.
Bei den Labels ist es einfacher, Dort kann ich durch Ziehen der äußeren Eckpunkte die Größe ändern. Den Code dazu findest du hier im Forum.

Um das zu verdeutlichen hab ich noch mal was in den Anhang gelegt.

Bei den Connectoren entstand zusätzlich das Problem, dass das Control ein Viereck ist, aber nur die Linien sichtbar sein sollen. Geht also ein Verbinder von links oben nach rechts unten, so würde er alle anderen Elemente verdecken (optisch und für Maus-Aktionen). Suche im Forum nach "durchklickbar", dann findest du entsprechende Beispiele für die Verwendung von Ranges.

Ich helfe dir gerne bei deinem Problem, möchte aber nicht den kompletten Code hier posten. erstens habe ich das Projekt nicht als open Source angelegt, zweitens ist auch noch nicht alles fertig.
Funktionen wie:
- Ausrichten am Gitter
- Fixieren an anderen (meinen) Controls
- Verbindung von Eingangs-/Ausgangs-Gates
- Anzeige und Bearbeitung von Eigenschaften

sind nicht oder nur teilweise umgesetzt. Arbeite ich halt dran.

Gruß oki

torud 15. Aug 2007 12:19

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo,

es tut mir leid, wenn ich Deinen Ausführungen zwar inhaltlich folgen kann, aber eigentlich mit der Umsetzung total überfordert bin. Ich habe folgenden Link gefunden, der das Zeichnen eines Pfeiles von x,y nach x,y schon mal realisiert.

http://www.delphipraxis.net/internal...t.php?p=290736

Das hat zwar mit dem was Du tust, nichts zu tun, aber es bringt mich ein Stück weiter. Allerdings bin ich mit dieser Lösung KEINEN Schritt voran gekommen, da ich damit nur einen Pfeil zeichnen kann, aber danach habe ich nen Pfeil auf nem Canvas und habe eher keine Chance diesen zu bewegen oder zu löschen oder sonstwas mit ihm anzustellen...

Also weiss ich jetzt zwar, wie ich einen Pfeil zeichne, aber ich weiss noch nicht genau, worauf ich ihn zeichnen soll. Wie wäre es mit einem TLabel? Oder welche Frage muss ich mir stellen, um wieder einen Schritt voran zu kommen?

Bezüglich der Linien des Pfeiles gefallen mir die grässlichen Treppchen nicht. Aber ich habe auch blos keine Ahnung, wie man die wegbekommen kann. AntiAlaising!?

torud 15. Aug 2007 12:45

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Ich habe gerade festegestellt, dass ich zwar gelernt habe, wie man Pfeile zeichnen lassen kann und dies dahingehend erweitert, dass ich erstmal die Pfeile von einem Button zum anderen zeichnen lasse, aber nachdem das Fenster mal im Hintergrund war, war durch ein Repaint des Fensters nichts mehr zu sehen von den Pfeilen. Eigentlich logisch.

Also muss ich wohl oder über auf eine Control zeichnen.

Da scheint sich langsam der Kreis zu schliessen...Ich denke, dass ich jetzt dann zu TCustomControl gelangen werde!?

oki 15. Aug 2007 12:55

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Zitat:

Zitat von torud
Da scheint sich langsam der Kreis zu schliessen...Ich denke, dass ich jetzt dann zu TCustomControl gelangen werde!?

Joop,

Somit hast du dein eigenes Control (TArrowControl), mit dem du alles notwendige anstellen kannst.
Implementiere in dein neues Control eine Methode:
Delphi-Quellcode:
procedure DrawArrow;
procedure Paint; override;

procedure TArrowControl.Paint;
begin
  inherited;
  DrawArrow;
end;
In die Procedure DrawArrow packst du deinen Code für das Zeichen deines Pfeiles.

Registriere dieses Control als Komponente in einer eigenen Seite deiner IDE. Dann kannst du es zur Designzeit verwenden.

Gruß oki

torud 15. Aug 2007 13:51

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ehrlich gesagt ist das zu viel des Guten. Ich habe zum einen noch keine eigene Komponente erstellt und weiss auch nicht sooo recht, was Du da schreibst...Allerdings habe ich festgestellt, dass selbst der Cnavas des TLabels nach dem Neuzeichnen des Forms leer ist.

Ich erlaube mir mal mein Demo-Projekt anzuhängen, in der Hoffnung, dass Du oder ein andere mal testet und mir etwas weitere Hilfe gewährt...

Zur Funktionalität: Einfach nur auf einen Button klicken und danach auf einen anderen button klicken. Beim 2. Buttonklick wird dann ein Pfeil vom ersten zum zweiten Button gezeicht, in ein Label, welches nicht generiert wurde, sondern alClient auf dem Form selbst liegt...

Das dynamische Generieren eines Labels sollte kein Problem sein. Auch das ausrichten der Pfeile, die derzeit noch immer von oben links starten ist kein Problem, aber ich verstehe nicht wirklich alles von dem was Du da schreibst...Schaust Du bitte mal drüber...?

oki 15. Aug 2007 14:35

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hi,

also, du hast jetzt zwei Möglichkeiten.

1. Du zeichnest alles auf deine Form. Dann ist das halt gezeichnet. Verschieben einzelner Elemente (Pfeile etc.) ist dann aber nicht möglich. Halt nur neu zeichen. Dein Formular hat ein Ereignis OnPaint. Wenn alles nach dem "Neuanzeigen" wieder gezeichnet werden muß, dann rufe deine Zeichenmethode von dort auf.

2. Du estellst dir eigene Controls. Dann empfehle ich dir dich erst mal mit der Erstellung eigener Klassen und Komponenten zu beschäftigen.

Gruß oki

oki 15. Aug 2007 16:34

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
ok, jetzt mit etwas mehr Zeit.

In deinem Demo zeichnest du zur Laufzeit die Linien und die Pfeile in den Canvas. Das erfolgt aber nur, wenn du auf den Button klickst. Wird dein Fenster neu gezeichnet, so musst du natürlich dafür sorgen, dass auch deine Linien und Pfeile neu gezeichnet werden. Um das zu ereichen, mußt du deine Zeichenmethoden in das OnPaint-Ereignis verlagern oder die Methode Paint des Controls (Fensters) auf dessen Canvas du zeichnest überschreiben.
Zusätzlich ist es natürlich notwendig, dass du einen Start und Endpunkt hast.

Fang mal einfach an. Lege einen Startpunkt und endpunkt im Code fest. Dann verlagere das, was du bei deinem ButtonClick machst in eine Procedure. Schreibe den Namen dieser Procedure in das OnPaint-ereignis.
schwups wird immer dein Pfeil gezeichnet.

Solltest du so nicht weiter kommen, so sag bescheid. Dann schau ich mir dein Demo mal genauer an und überarbeite den Code.

Gruß oki

torud 15. Aug 2007 17:50

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo,

wie ich ein eigenes TControl zur Laufzeit erstelle ist mir natürlich klar. Das ist nicht das Problem. Ich bin also schon in der Lage in TLabel zur Laufzeit zu erstellen und es so zu platzieren, dass es Sinn macht und dann darauf den Pfeil zu zeichnen. Das ist kein Problem.

Aber wie verhindere ich, dass der Pfeil verschwindet, wenn das Form oder das Label selbst neu gezeichnet wird!?

Diese Frage impliziert die Entscheidung zur Variante 2. Ich habe aber nicht vor, mir deshalb eine eigene Komponente zu programmieren, wenns sich nicht wirklich vermeiden lässt...

oki 15. Aug 2007 18:33

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hei torud,

das Erstellen zur Laufzeit reicht halt nicht. Die Klasse muß auch neue Eigenschaften besitzen. Halt Pfeil zeichnen. Kennst du eine Kompo oder Klasse die das kann?
Ich denke nicht, sonst würdest du nicht fragen :lol:

Also brauchst du eine neue Klasse! Ob du daraus auch gleich mittels Register eine Komponente in deiner IDE machst bleibt dir überlassen.
Dieser neuen Klasse mußt du jetzt die Eigenschaft Pfeil zeichnen verpassen. Dazu gehören die entsprechenden Start- und Endpunkte deiner Linie und an welchem Punkt der Pfeil gezeichnet werden soll. Dann noch eine Procedure, die alles in den Canvas zeichnet, aufgerufen in der vererbten Procedure Paint und fertig.

Das wars schon.

Gruß oki

torud 15. Aug 2007 19:45

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Ok, ich denke...das das dann mit nem neuen Thema verbunden ist und werde dann wohl nen neuen Thraed aufmachen oder aber mich zum Thema Erstellung einer Komponente beschäftigen...Muss ja auch lösbar sein oder!?

Soll ich nun ein TLabel nehmen oder bietet sich nicht ein TShape an?
Und wie stellt man sicher, dass der gezeichnete Pfeil nicht immer verschwindet?

Hawkeye219 15. Aug 2007 20:17

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo Tom,

ich habe hier eine kleine Demo zusammengebaut, die dir zeigen soll, wie du möglicherweise auf eine Pfeil-Komponente verzichten kannst. Zum Testen benötigst du lediglich ein leeres Formular, auf das du zwei Panels (Panel1 und Panel2) legst. Die Ereignisse OnMouseDown, OnMouseMove und OnMouseUp der Panels verbindest du über den Objektinspektor mit den zugehörigen Methoden des folgenden Codes. Das Ereignis OnPaint des Formulars verbindest du mit der Methode FormPaint. Wenn du nun die Anwendung startest, solltest du beide Panels mit der Maus verschieben können. Ein Pfeil verbindet Panel1 mit Panel2.
Delphi-Quellcode:
// uses Math;
type
  TForm1 = class (TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    procedure FormPaint (Sender: TObject);
    procedure PanelMouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure PanelMouseMove (Sender: TObject; Shift: TShiftState; X,Y: Integer);
    procedure PanelMouseUp (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  private
    FAnchor : TPoint;  // Mausposition zu Beginn des Verschiebens
    FOrgPos : TPoint;  // Position des Controls vor dem Verschieben
    FPanning : Boolean; // True während des Verschiebens
  end;

CONST
  GRIDINTERVAL = 16;

type
  TPin = (pinBody, pinLeft, pinTop, pinRight, pinBottom);

// zeichnet einen Vektor mit einer Pfeilspitze
procedure DrawVector (aCanvas: TCanvas;
                      x1, y1, x2, y2: Integer;
                      aHeadSize: Integer = 5;
                      aFillHead: Boolean = False);
const
  ApexAngle = 30 * Pi / 180;
var
  dx, dy : Integer;
  angle : Double;
  s1, c1 : Extended;
  s2, c2 : Extended;
  P1, P2 : TPoint;
begin
  aCanvas.MoveTo (x1, y1);
  aCanvas.LineTo (x2, y2);

  if (x1 <> x2) then
    angle := {Math.}ArcTan2(y2 - y1, x2 - x1)
  else
    if (y1 < y2) then
      angle := Pi / 2
    else
      angle := 3 * Pi / 2;

  {Math.}SinCos (angle - ApexAngle, s1, c1);
  {Math.}SinCos (angle + ApexAngle, s2, c2);

  P1.x := x2 - Round(c1 * aHeadSize);
  P1.y := y2 - Round(s1 * aHeadSize);
  P2.x := x2 - Round(c2 * aHeadSize);
  P2.y := y2 - Round(s2 * aHeadSize);

  if aFillHead then
    aCanvas.Polygon ([P1, Point(x2, y2), P2])
  else
    begin
      aCanvas.MoveTo (P1.x, P1.y);
      aCanvas.LineTo (x2, y2);
      aCanvas.MoveTo (P2.x, P2.y);
      aCanvas.LineTo (x2, y2);
    end;
end;

// Liefert die Position eines Anschlußpunktes für ein Control
function PinPosition (aControl: TControl; aPin: TPin): TPoint;
var
  w2, h2 : Integer;
begin
  w2 := aControl.Left + aControl.Width div 2;
  h2 := aControl.Top + aControl.Height div 2;
  case aPin of
    pinLeft: Result := Point(aControl.Left, h2);
    pinTop: Result := Point(w2, aControl.Top);
    pinRight: Result := Point(aControl.Left + aControl.Width, h2);
    pinBottom: Result := Point(w2, aControl.Top + aControl.Height);
  else
    Result := Point(w2, h2);
  end;
end;

procedure TForm1.PanelMouseDown (Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FAnchor := Mouse.CursorPos;
  FOrgPos := TControl(Sender).BoundsRect.TopLeft;
  FPanning := True;
end;

procedure TForm1.PanelMouseMove (Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  xPos, yPos : Integer;
begin                                          
  if FPanning then
    begin
      xPos := FOrgPos.X + (Mouse.CursorPos.X - FAnchor.X);
      yPos := FOrgPos.Y + (Mouse.CursorPos.Y - FAnchor.Y);
      TControl(Sender).Left := xPos - (xPos mod GRIDINTERVAL);
      TControl(Sender).Top := yPos - (yPos mod GRIDINTERVAL);
      Invalidate;
    end;
end;

procedure TForm1.PanelMouseUp (Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FPanning := False;
end;

procedure TForm1.FormPaint (Sender: TObject);
var
  P1, P2 : TPoint;
begin
  inherited;
  // zeichne eine Verbindung von Panel1 (rechter Anschlußpunkt) zu Panel2 (linker Anschlußpunkt)
  P1 := PinPosition(Panel1, pinRight);
  P2 := PinPosition(Panel2, pinLeft);
  Canvas.Pen.Color := clBlue;
  Canvas.Brush.Color := clBlue;
{
  Canvas.Pen.Width := 2;
  Canvas.MoveTo (P1.X, P1.Y);
  Canvas.LineTo (P2.X, P2.Y);
}
  DrawVector (Canvas, P1.X, P1.Y, P2.X, P2.Y, 10, True);
end;

end.
Im Beispiel wird eine feste Verbindung eingezeichnet, in deiner Anwendung wirst du diese Verbindung variabel gestalten wollen. Du mußt dir dazu überlegen, wie du die beiden beteiligten Controls zusammen mit den benutzten Anschlußpunkten verwalten kannst.

Der Code wird sicher nicht genau dem entsprechen, was du dir vorstellst, er soll lediglich das Prinzip zeigen. Um die Treppen bei den Linien zu entfernen, könntest du das Graphics32-Paket einsetzen. Es unterstützt auch die Kantenglättung (antialiasing) bei Linien.

Gruß Hawkeye

torud 16. Aug 2007 06:42

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo Hawkeye,

vielen Dank für Dein Beispiel. Ich finde es so wie es ist schon ganz ok. Nun kommen die ABERS...für die ich sicher selbst versuchen muss eine Lösung zu finden.

Die Pfeile sind nicht verwaltbar.
Sie nicht verschiebbar oder sonstwie editierbar. Logisch, sie folgen ja automatisch ihrer Bindung. Das ist auch gut so!
Die Pfeile gehen nicht umme Ecke. :-) => Das ist sicher auch einer der schwierigen Abschnitte. Auch wandert die Pfeilspitze und der Linienanfang nicht mit, wenn man die Seiten der Panels vertauscht.

Ich könnte mir zwar im Hintergrund eine Liste halten, wo ich mir nortiere, welche Controls miteinander verbunden sind und dann desweiteren noch notieren, was für ein Pfeil zwischen den Controls ist (Farbe,Style usw.) aber ich denke, dass das ziemlich aufwendig ist.

Ich denke insgesamt, ist das eigentlich schon ein Riesenprojekt für sich, an dem mich wundert, dass es sowas noch nicht gibt. Die Jungs von TMS haben zwar sowas schon, aber geht dies nur in deren DiagrammStudio. Ansonsten habe ich nicht wirklich viel zu diesem Thema finden können.

Zum einen wäre es das allereinfachste eine Komponente zu haben, die man einfach nur platziert und man hat einen fertigen Pfeil, den man in der Grösse, Drehrichtung, Farbe und sonstigem Styling anpassen kann. Wenn dieser noch an dere Control gedockt werden kann, wäre es perfekt.

Ich schwanke noch zwischen den beiden Lösungen, weiss aber auch, dass ich nicht in der Lage sein werde, sowas komplett allein zu erstellen...Was sind Eure Favoriten!?

oki 16. Aug 2007 08:18

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hi torud,
Zitat:

Zitat von torud
Ich könnte mir zwar im Hintergrund eine Liste halten, wo ich mir nortiere, welche Controls miteinander verbunden sind und dann desweiteren noch notieren, was für ein Pfeil zwischen den Controls ist (Farbe,Style usw.) aber ich denke, dass das ziemlich aufwendig ist.

und aus diesem Grund gibt es OOP.
In dem du es in einer Klassen kapselst programmierst du das Verhalten incl. der Eigenschaften einmal und erstellst zur Laufzeit mehrere Instanzen (bei dir also Pfeile). Wenn du in deiner Klasse eine Eigenschaft LineColor definierst, dann nimmst du beim zeichnen eben nicht eine feste Farbe, sonder FLineColor. Jedes Pfeilobjekt hat somit sein eigenes LineColor was es sich selber merkt.
Ich denke Hawkeye hat sein einfaches Beispiel ganz bewust so gewählt. Du hast zur Zeit zwei wesentliche Probleme:
1. dir ist das Prinzip von OOP noch nicht ganz klar,
2. du hast noch kein "Gefühl" dafür wie das Prinzip der VCL abläuft.

Mit Hawkeye's Beispiel kannst du eventuell den 2. Punkt etwas klarer sehen. Da siehst du gut, wie das mit dem Zeichnen und darstellen abläuft, ohne das dir gleich einer was von eigenen Controls erzählt.
An deiner Stelle würde ich Hawkeye's Beispiel nehmen und versuchen die fehlenden Sachen zu ergänzen. Dann schaun wir weiter. Der weg zur eigenen Klasse ist dann auch nicht weit.

Gruß oki

torud 18. Aug 2007 12:04

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hello Again,

ich danke Euch beiden für Eure hilfreichen Tipps und den Hinweis darauf, dass ich meine Schwachstellen abdichten muss. Ich gelobe Besserung. => Binsoweit, dass der Pfeil fast richtig mitwandert...

Ich habe mich etwas mit dem Beispiel auseinandergesetzt, da ich finde, dass ich schon verstehen muss, was da passiert und sicher einiges davon gebrauchen kann, was drin geschrieben steht. Ich beziehe mich jetzt also auf das Beispiel mit den beiden Panels.

Dort gibt es die Routine FormPaint, wo bisher geschrieben stand, von wo nach wo der Pfeil gezeichnet werden soll. Ich habe versucht diese Routine zu verfeinern, bin aber nicht wirklich glücklich mit der Lösung, da ich, wie ich finde eigentlich einen Winkel um jeden Pin legen müsste. Wenn sich das andere Panel in einem der Winkel befindet, oder es tangiert, wäre klar, dass von wo nach wo der Pfeil gezeichnet werden muss.

Da mir dazu die Routine fehlt, habe ich es erstmal provisorisch so gelöst:

Delphi-Quellcode:
procedure TForm1.FormPaint (Sender: TObject);
var
  P1, P2 : TPoint;
begin
  inherited
  if Panel1.Top > Panel2.Top + Panel2.Height then P1 := PinPosition(Panel1,pinTop);
  if Panel1.Top < Panel2.Top + Panel2.Height then P1 := PinPosition(Panel1,pinBottom);
  if Panel1.Top = Panel2.Top then P1 := PinPosition(Panel1,pinRight);

  if Panel1.Left < Panel2.Left then P2 := PinPosition(Panel2,pinLeft);
  if Panel1.Left > Panel2.Left then P2 := PinPosition(Panel2,pinLeft);
  if Panel1.Left = Panel2.Left then
    if Panel1.Top < Panel2.Top then P2 := PinPosition(Panel2,pinTop);
    if Panel1.Top > Panel2.Top then P2 := PinPosition(Panel2,pinBottom);
   {und dann der rest vom Schützenfest}
end;
Der Code könnte Fehler beinhalten, da ich ihn mit der Hand abschreiben musste. Sitze hier an einem Rechner, wo ich nicht mal eben den Code vom Stick kopieren kann.

Problem oder Unsauberkeit des Codes ist, dass Pfeil nur dann Rechts oder Links angedockt wird, wenn die beiden Panels auf gleicher Höhe sind. Besser wäre aber, wenn in der Routine ein gewisser Bereich berücksichtigt werden würde.

Skizziert sieht das ganz einfach aus. man zeichne ein Panel in die Mitte und ziehe linien diagonal durch. Die dadurch enstehenden 4 Bereiche sind die Bereiche, die wichtig sind. Wie kann ich das nun ermitteln???

oki 20. Aug 2007 08:40

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hi torud,
Zitat:

Skizziert sieht das ganz einfach aus. man zeichne ein Panel in die Mitte und ziehe linien diagonal durch. Die dadurch enstehenden 4 Bereiche sind die Bereiche, die wichtig sind. Wie kann ich das nun ermitteln???
Das ist dann mal pure Mathematik. Du musst die Graphen (Funktion der Geraden) der beiden Diagonalen durch dein erstes Panel ermitteln. Die entsprechenden Eckpunkte hast du ja. Erster Graph links/oben nach rechts/unten. Zweiter Graph links/unten nach rechts/oben.

Dann nimmst du deinen Verbindungspunkt deines zweiten Panels und berechnest für die Koordinatenwerte die entsprechende Lage der Graphen. Mit einfacher <> Prüfung auf X und Y kannst du dann den "Quadranten" (eigentlich sind es ja keine) ermitteln, in dem dein zweites Panel in Bezug auf dein erstes Panel liegt. danach dei festgelegten Punkte verbinden. Die Festlegung der Typen für pinTop etc. sind übriegens sehr gut. Das erhöht ungemein die Lesbarkeit des Codes.

Gruß oki

torud 20. Aug 2007 09:29

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
also das klingt jetzt ganz schön kompliziert. ich werde mal das forum nach graphen und alldem, was du da geschrieben hast, durchsuchen, da mein mathe mehr als eingerostet ist und ich zwar alles mögliche im kopf rechne, aber winkelfunktionen und dergleichen zuletzt vor ca. 19 jahren hatte... :shock:

mir ist schon klar, dass bei dem zeichnen der diagonalen 4 dreiecke entstehen und ich nur checken muss, ob das 2. panel in einem der bereiche ist.

Hawkeye219 20. Aug 2007 12:20

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo Tom,

die Position der beiden beteiligten Panels zueinander läßt sich recht einfach mit dem Sutherland-Cohen-Algorithmus ermitteln. In Abhängigkeit des ermittelten Lagecodes wird dann der Pfeil gezeichnet.

Delphi-Quellcode:
procedure TForm1.FormPaint (Sender: TObject);

  procedure DoDrawVector (aPin1, aPin2: TPin);
  var
    P1, P2 : TPoint;
  begin
    P1 := PinPosition(Panel1, aPin1);
    P2 := PinPosition(Panel2, aPin2);
    Canvas.Pen.Color := clBlue;
    Canvas.Brush.Color := clBlue;
    DrawVector (Canvas, P1.X, P1.Y, P2.X, P2.Y, 10, True);
  end;

var
  code : Integer;
begin
  inherited;

  // Lagecode des ersten Panels bezogen auf das zweite Panel ermitteln
  code := 0;
  if (Panel1.Left + Panel1.Width < Panel2.Left) then Inc (code, 1);
  if (Panel1.Left > Panel2.Left + Panel2.Width) then Inc (code, 2);
  if (Panel1.Top + Panel1.Height < Panel2.Top) then Inc (code, 8);
  if (Panel1.Top > Panel2.Top + Panel2.Height) then Inc (code, 4);

  // Vektor in Abhängigkeit des Lagecodes zeichnen
  case code of
    1: DoDrawVector (pinRight, pinLeft);
    2: DoDrawVector (pinLeft, pinRight);
    4: DoDrawVector (pinTop, pinBottom);
    5: DoDrawVector (pinTop, pinLeft);
    6: DoDrawVector (pinTop, pinRight);
    8: DoDrawVector (pinBottom, pinTop);
    9: DoDrawVector (pinBottom, pinLeft);
   10: DoDrawVector (pinBottom, pinRight);
  end;
end;
Die Lösung von oki (mehrere Ecken pro Verbindung) ist natürlich wesentlich ansprechender, aber auch etwas aufwendiger.

Gruß Hawkeye

torud 20. Aug 2007 12:32

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Wird sofort ausprobiert.
Feedback garantiert!

torud 21. Aug 2007 09:13

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

also das funktioniert nun schon ganz gut. Folgendes interessiert mich nun noch.

Wie kann ich den Pfeil auch mit einer gestrichelten Linie darstellen?
- Canvas.Pen.Style := psDashDot; //führte nicht zum Erfolg

Ist es möglich auch einen Doppelpfeil darstellen zu lassen?
- Ich denke, dass ich dazu DrawVector etwas modifizieren müsste...!?

Was muss ich tun, um den Pfeil mit Grafics32 besser aussehen zu lassen?
- Mich stören noch die Treppchen in der Linie.

Wie könnte ich intern die Pfeile verwalten?
- Ich weiss, das OKI sicher wieder darauf verweisen wird, dass es besser wäre eine eigene Extra-Komponente zu erstellen. Ich gebe ihm da auch recht, aber in der Kürze der Zeit ist das derzeit nicht drin.
--Anfang sollen also gar keine Pfeile zwischen den Controls sein. Der User soll auswählen können von wo nach wo ein Pfeil erstellt werden soll. Dazu müsste ich mir intern notieren:

- von Control
- nach Control
- Art der Pfeilspitze
- Farbe des Pfeiles
- Style der Pfeillinie

Bei jedem FormPaint müsste ich dann in einer Schleife die interne Liste abarbeiten und die Pfeile neuzeichnen. Was empfehlt ihr hierzu? Ich würde es in einer einer TStringlist vorhalten und die Eigenschaften eines jeden Pfeiles in einem Item Semikolon-getrennt schreiben und in einer Extraliste dem User visualisieren.

Gehts auch anders? Oder anders gefragt, macht es anders mehr Sinn?

Im Anhang mein aktuelles Beispiel...

Hawkeye219 21. Aug 2007 16:59

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo Tom,

Zitat:

Wie kann ich den Pfeil auch mit einer gestrichelten Linie darstellen?
- Canvas.Pen.Style := psDashDot; //führte nicht zum Erfolg
Damit Pen.Style akzeptiert wird, muß offenbar Brush.Style den Wert bsClear haben. Wenn die Pfeilspitze gefüllt werden soll, muß natürlich Brush.sStyle wieder auf den Wert bsSolid gesetzt werden. Es wäre somit besser, alle Zugriffe auf den Canvas in die Zeichenroutine zu verlagern.

Zitat:

Ist es möglich auch einen Doppelpfeil darstellen zu lassen?
- Ich denke, dass ich dazu DrawVector etwas modifizieren müsste...!?
Möglich ist das, es stellt sich aber die Frage, ob der jetzige Weg dafür der richtige ist. Deine Frage nach der Verwaltung der Pfeile geht ja in die gleiche Richtung. Es muß nicht unbedingt eine Komponente sein, die auf dem Formular abgelegt werden kann. Zunächst sollte man vielleicht alle Parameter einer Verbindung in einem Objekt TConnection kapseln. Die Zeichenroutine wird dann zu einer Methode dieses Objektes und kann auf die benötigten Daten zugreifen. Lediglich der Canvas für die Ausgabe muß ihr noch übergeben werden.

Zitat:

Was empfehlt ihr hierzu? Ich würde es in einer einer TStringlist vorhalten und die Eigenschaften eines jeden Pfeiles in einem Item Semikolon-getrennt schreiben und in einer Extraliste dem User visualisieren.
Wenn du die Kapselung wie oben beschrieben durchführst, genügt für die interne Speicherung der Daten schon eine TObjectList mit Verweisen auf die TConnection-Objekte.

Zitat:

Was muss ich tun, um den Pfeil mit Grafics32 besser aussehen zu lassen?
Hier muß ich leider passen, da ich noch nicht mit dieser Bibliothek gearbeitet habe. Da sie aber schon häufiger in diesem Forum empfohlen wurde, findet sich vielleicht jemand, der dir in diesem Punkt besser helfen kann.

Gruß Hawkeye

torud 24. Aug 2007 13:10

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Wissende,

im Anhang habe ich ein erstes Ergebnis als Bild angehangen. WIe ich finde nicht soo schlecht. Leider habe ich doch noch ein paar Fragen, da wie Ihr vielleicht zustimmen werdet, die Pfeile noch nicht optimal verlaufen.

Die Pfeile von Objekt 2 zu 3 und 5 wären mir OnTop wesentlich lieber, damit es einheitlicher wirkt.

Das Fenster zur Pfeileverwaltung zeige ich nur Modal an und sobald ich es über das Fenster mit den Pfeilen schiebe, werden diese gelöscht und erst dann neu gezeichnet, wenn ich auf die Paintbox klicke, die ich alClient auf die Scrollbox gelegt habe. Wie kann ich das umgehen?

Ich habe schon my_controls.PaintBox.Repaint; versucht, wenn ich das Fenster bewege und dann mit der Maus loslasse, aber es wird nicht neu gezeichnet.

Wenn ich die Objekte bewege und verschiebe, werden die Pfeile neu gezeichnet, aber die alten bleiben vorhanden. Erst wenn ich wieder auf die Paintbox klicke, werden alle Pfeile gelöscht und neu gezeichnet...

Die Ereignisse zu den Control bei MouseDown,MouseMove oder MouseUp musste rausnehmen, da ich eine andere Komponente zum verschieben der Controls benutze. Wenn ich diese Routinen anbinde, dann reicht es, wenn ich mit der Maus in die Nähe komme und schon laufen mir die Controls vor der Maus weg. Sieht zwar lsutig aus, aber ist so nicht zu gebrauchen. Ich werde mal sehen, was in den 3 Routinen gemacht wird, damit ich es vielleicht selbst woanders implementiere...

Über Ideen und Anregungen würde ich mich freuen...

torud 25. Aug 2007 06:59

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Das regelmäßige Zeichnen habe ich hinbekommen. Ich musste hier und da OnFormPaint aufrufen, bzw. in OnFormPaint das Zeichnen der Paintbox anbinden. Die restlichen Fragen sind leider noch offen...

Hawkeye219 25. Aug 2007 10:31

Re: Suche Pfeile zur Visualisierung von Beziehungen
 
Hallo Tom,

die Anschlußpunkte für die Pfeile kannst du frei bestimmen, du mußt nur geeignete Bedingungen für die Auswahl der Parameter von DoDrawVector finden. In meinem Beispiel habe ich diese Parameter einfach in Abhängigkeit des Lagecodes gewählt. Du wirst wahrscheinlich weitere Informationen einfließen lassen, z.B. den x- oder y-Abstand der beteiligten Panels oder die Steigung des Verbindungspfeils.

Gruß Hawkeye


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:41 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