Änderungen

Wechseln zu: Navigation, Suche

Draw2d

9.406 Byte hinzugefügt, 10:59, 15. Jul. 2010
= Draw2d === Einführung ==
Draw2d ist ein auf Diagrammenzeichnung orientiertes Vektorgrafik-Toolkit für Eclipse. Es ist als Teil von GEF entstanden, kann aber unabhängig von GEF benutzt werden. Draw2d weist nicht so viele Möglichkeiten für eine komplizierte Grafikdarstellung auf, legt aber Akzent auf die in verschiedenen Diagrammentypen vorkommende Elemente wie z.B. rechteckige Blöcke mit Text oder Verbindungslinien jeglicher Art. Es bietet weiter die Möglichkeiten für eine automatische Anordnung der Elemente auf der Zeichnung sowie das sogenannte "Hit Testing" - die Erkennung des Elementes unter dem Mauszeiger.
<br>
Jedes sichtbare draw2d-Objekt ist eine Figur.
== Packages ==
* org.eclipse.draw2d - alle wichtigsten Klassen sind hier definiet.
* org.eclipse.draw2d.geometry - Basisklassen für geometrische Objekte wie Punkte, Vektoren, Rechtecke usw.
In der Methode ''paint'' muss eine Figur sich Zeichnen. Dafür hat sie die Methoden der abstrakten Klasse org.eclipse.draw2d.Graphics zur
Verfügung.
== "Hello world" in draw2d ==
In diesem Beispiel wird die Zusammenarbeit von SWT und draw2d demonstriert. Ausserdem sieht man hier, wie die Wurzelfigur für das LightweightSystem eingestellt wird und wie ein Figurenbaum entsteht.
<br>
In diesem Beispiel werden zwei Figuren erstellt, ''contents'' und ''label''. Das ''label'' wird mit ''add'' an das ''contents'' angehängt, ''contents'' wird als Wurzelfigur im ''lwSystem'' gesetzt. Damit man die Wurzelfigur ''contents'' sehen kann, wird ihr ein dicker Rahmen hinzugefügt.
== Zeichnungsreihenfolge und Überlappung der Figuren ===Die Figuren bilden eine Baumhierarchie. Die Zeichnung fängt vom Wurzel des Baums an - das bedeutet, dass die Kinder-Objekte nach den Eltern-Objekten gezeichnet werden und stehen deswegen immer im Vordergrund zu ihren Eltern. Jede Figur verwaltet ihre Kinder in einer geordneten Liste. Die Reihenfolge, in der die Kinder gezeichnet werden, entspricht ihrer Reihenfolge in dieser Liste. Deswegen überlappen die Kinder mit dem größeren Index die mit dem kleineren.<br>Wenn die Kinder zu groß für die Zeichenfläche einer Eltern-Figur sind, werden sie am Rand der Eltern-Figur abgeschnitten. = Verbindungen und Routing ===== Verbindungen und Anker ===
Eine spezielle Art der Figuren sind die Verbindungen. Verbindungen müssen das Interface ''Connection'' implementieren, das das ''IFigure'' erweitert.
<br>
<br>
=== Routing ===Wie man oben gesehen hat, zeichnet die ''PolylineConnection'' eine gerade Linie zwischen den von Anker festgelegten Punkten. Oft braucht man aber die Möglichkeit, die Linien anderer Formen zu zeichnen. In diesem Fall kann man eine neue Implementierung von ''Connection'' entwickeln. Es besteht aber eine einfachere Möglichkeit - das ''Connection''-Objekt mit einem ''ConnectionRouter'' zu parametrieren. Das macht man mit der Methode ''Connection.setConnectionRouter''. ''ConnectionRouter'' ist ein Interface in draw2d, vom dem es mehrere fertige Implementierungen gibt:* ''AbstractRouter'' - abstrakte Klasse mit einigen Hilfsfunktionen.* ''AutomaticRouter'' - abstrakte Klasse mit "Collision Detection" - Erkennung überlappender Verbindungen. Die Auflösung des Konflikts müssen die abgeleiteten Klassen übernehmen.* ''FanRouter'' - eine Ableitung von ''AutomaticRouter'' mit Konfliktauflösung. Die Konflikte werden so gelöst, dass mehrere Verbindungen zwischen zwei gleichen Punkten unterschiedlich geführt werden und eine Art Ventilatorschaufel bilden.* ''BendpointConnectionRouter'' - führt die Linie über die in einer Liste gegebenen Punkte.* ''ShortestPathConnectionRouter'' - finden den kürzesten Pfad, der alle Kinder einer gegebenen Figur meidet.* ''ManhattatConnectionRouter'' - erzeugt eine rechteckige Verbindung mit nur senkrechten und waagerechten Linien.<br>Hier ein Beispiel mit dem ''ManhattanConnectionRouter'':<br><source lang=java> Label label1 = new Label("Label 1"); LineBorder borderL1 = new LineBorder(); label1.setBounds(new Rectangle(10, 10, 100, 30) ); label1.setBorder(borderL1); contents.add(label1); Label label2 = new Label("Label 2"); label2.setBounds(new Rectangle(150, 150, 100, 30) ); label2.setBorder(borderL1); contents.add(label2); ManhattanConnectionRouter router = new ManhattanConnectionRouter(); PolylineConnection connection = new PolylineConnection(); connection.setConnectionRouter(router); connection.setSourceAnchor(new ChopboxAnchor(label1) ); connection.setTargetAnchor(new ChopboxAnchor(label2) ); contents.add(connection);</source><br>Und der Output:<br>[[Datei:dratva_1919_example6_draw2d.png]]<br>== Decorations ==Das letzte Beispiel wird jetzt modifiziert:<br><source lang=java> Label label1 = new Label("Label 1"); LineBorder borderL1 = new LineBorder(); label1.setBounds(new Rectangle(10, 10, 100, 30) ); label1.setBorder(borderL1); contents.add(label1); Label label2 = new Label("Label 2"); label2.setBounds(new Rectangle(150, 150, 100, 30) ); label2.setBorder(borderL1); contents.add(label2); ManhattanConnectionRouter router = new ManhattanConnectionRouter(); PolylineConnection connection = new PolylineConnection(); connection.setConnectionRouter(router); connection.setSourceAnchor(new ChopboxAnchor(label1) ); connection.setTargetAnchor(new ChopboxAnchor(label2) ); PolygonDecoration decoration = new PolygonDecoration(); connection.setTargetDecoration(decoration); contents.add(connection);</source><br>Der Output von diesem Programm sieht so aus:<br>[[Datei:dratva_1919_example7_draw2d.png]]<br><br>Wie man sieht, wurde hier ein Pfeil an einem Ende der Linie gezeichnet. Das wurde mit dem Aufruf von ''connection.setTargetDecoration'' erreicht. Es gibt eine entsprechende Methode für den Anfang der Linie, ''setSourceDecoration''. Für das Decoration selbst wurde hier ''PolygonDecoration'' verwendet. In draw2d gibt es noch eine Decoration-Implementierung, ''PolylineDecoration''. Und man darf natürlich eigene Decorations implementieren. Sie müssen das Interface ''RotatableDecoration'' implementieren.<br>Die Klassen ''PolygonDecoration'' und ''PolylineDecoration'' zeichnen standardmäßig einen Pfeil. Sie besitzen aber die Methode ''setTemplate'', mit der man das Aussehen von diesem Decoration ändern kann. Das wird im nächsten Beispiel demonstriert. Hier wird auch das ''ManhattanRouting'' weggenommen, um das Rotieren des Templates deutlicher zu zeigen. <br><source lang=java> Label label1 = new Label("Label 1"); LineBorder borderL1 = new LineBorder(); label1.setBounds(new Rectangle(10, 10, 100, 30) ); label1.setBorder(borderL1); contents.add(label1); Label label2 = new Label("Label 2"); label2.setBounds(new Rectangle(150, 150, 100, 30) ); label2.setBorder(borderL1); contents.add(label2); //ManhattanConnectionRouter router = new ManhattanConnectionRouter(); PolylineConnection connection = new PolylineConnection(); //connection.setConnectionRouter(router); connection.setSourceAnchor(new ChopboxAnchor(label1) ); connection.setTargetAnchor(new ChopboxAnchor(label2) ); PointList template = new PointList(); template.addPoint(0, 0); template.addPoint(-4, 2); template.addPoint(-2, 0); template.addPoint(-4, -2); PolygonDecoration decoration = new PolygonDecoration(); decoration.setTemplate(template); connection.setTargetDecoration(decoration); contents.add(connection);</source><br>[[Datei:dratva_1919_example8_draw2d.png]]<br>Man sieht hier deutlich, wie der Muster definiert wird, und wie die automatische Rotation funktioniert. Bei der Definition des Templates muss man sich vorstellen, dass die Verbindungslinie waagerecht ist und der Anfang des Koordinatensystems am Endpunkt der Linie sich befindet. Die negative X-Richtung ist dann die Richtung zum Zentrum der Linie. Beim Zeichnen wird der Muster um den Winkel rotiert, den die Verbindungslinie (oder ihr letzter Abschnitt im Fall einer Polylinie) zu der X-Achse bildet. = Rahmen =Mit der Methode ''setBorder'' des Interfaces ''IFigure'' kann man einer Figur einen Rahmen zuordnen. Für die Rahmen-Objekte ist das Interface ''Border'' definiert. Wie bei anderen wichtigen Elementen, gibt es auch von ''Border'' viele fertige Implementierungen, die sich äußerlich unterscheiden. Man könnte alle vorgefertigten Rahmentypen in drei Gruppen verteilen. Das sind * Einfache Linienrahmen (z.B. ''LineBorder'')* Rahmen, die nach GUI-Elementen (z.B. Buttons) aussehen, das heißt gesenkt oder erhöht aussehen (z.B. ''SimpleLoweredBorder'')* Rahmen mit einer Beschriftung (abgeleitet von ''AbstractLabeledBorder'')<br>Der Rahmen wird als letztes beim Zeichnen einer Figur augegeben. Deswegen ist er immer im Vordergrund im vergleich mit anderen Teilen der Figur. Die neue experimentelle Klasse ''AbstractBackground'' soll ermöglichen, auch im Hintergrund einer Figur die Teile des Rahmens zu zeichnen.<br>Mit der Klasse ''CompoundBorder'' kann man mehrere Rahmen kombinieren. = Layer =''Layer'' ist ein spezieller Typ von Figuren. Die ''Layer'' sind transparent optisch und auch für die Ereignisse. Das bedeutet, dass die GUI-Ereignisse wie z.B. Maus-Ereignisse sowie die "Hit Tests" werden tranparent an hinteren Figuren geleitet. Die ''Layer'' sind dafür gedacht, explizit nur in den ''LayerPanes'' benutzt zu werden. = Anordnungen (''Layouts'') =Die ''Layouts'' legen fest, wie die Parent-Figur ihre Kinder platziert. Ein ''Layout'' ist eine Implementierung des Interfaces ''LayoutManager''. Es gibt mehrere Standardimplementierungen in draw2d:* ''AbstractLayout'' - eine abstrakte Implementierung mit vielen Hilfsfunktionen* ''AbstractHintLayout'' - Basisklasse für die ''Layouts'', die die bevorzugte Größe der Figuren berücksichtigen.* ''ToolbarLayout'' - die Kinder werden senkrecht oder waagerecht an einer Linie platziert. <br>In folgenden Beispielen werden die Figuren wie folgt erzeugt:<br><source lang=java> Label label1 = new Label("Label 1"); LineBorder borderL1 = new LineBorder(); label1.setBounds(new Rectangle(10, 10, 100, 30) ); label1.setBorder(borderL1); contents.add(label1); Label label2 = new Label("Label 2"); label2.setBounds(new Rectangle(150, 150, 100, 30) ); label2.setBorder(borderL1); contents.add(label2); Ellipse ellipse = new Ellipse(); ellipse.setBackgroundColor(ColorConstants.blue); ellipse.setBounds(new Rectangle(0, 0, 20, 40) ); ellipse.setOpaque(true); contents.add(ellipse); RectangleFigure rectangle = new RectangleFigure(); rectangle.setBounds(new Rectangle(20, 40, 120, 30) ); rectangle.setOpaque(true); rectangle.setBackgroundColor(ColorConstants.red); contents.add(rectangle);</source><br>Ohne Anordnung erzeugen sie folgenden Output:<br>[[Datei:dratva_1919_example9_draw2d.png]]== ''ToolbarLayout'' ==Folgender Code benutzt das ''ToolbarLayout'', um die Kinder senkrecht darzustellen:<br><source lang=java> ToolbarLayout layout = new ToolbarLayout(); layout.setStretchMinorAxis(false); contents.setLayoutManager(layout);</source><br>Und so sieht jetzt der Output aus:<br><br>[[Datei:dratva_1919_example10_draw2d.png]]<br><br>Die Zeile mit dem Aufruf von ''setStretchMinoxAxis'' sagt dem ''LayoutManager'', die Objekte in der X-Achs nicht zu dehnen. Wenn man diese Zeile weg lässt, sieht der Output so aus:<br><br>[[Datei:dratva_1919_example10_1_draw2d.png]]<br><br>Mit dem folgenden Code kann man die Richtung der Anordnung um 90 Grad drehen:<br><source lang=java> ToolbarLayout layout = new ToolbarLayout(); layout.setStretchMinorAxis(false); layout.setVertical(false); contents.setLayoutManager(layout);</source><br><br>Und so sieht es aus:<br><br>[[Datei:dratva_1919_example10_2_draw2d.png]]<br>
== Anordnung ==[[Kategorie:Draw2d]]
258
Bearbeitungen