In den bisherigen Beispielprogrammen sind uns schon des öfteren die Routinen
Graphics2D.fill(Shape s)
und Graphics2D.draw(Shape s)
begegnet. Die Operationen, die man mit diesen Methoden ausführt, heißen
Painting und Stroking. Sie werden - besonders das Stroking - in diesem
Kapitel behandelt.
Als Painting bezeichnet man das Füllen eines Umrisses (Shape
-Objekt)
mit einer Farbe (Paint
-Objekt). Umrisse werden
in einem Graphics2D
-Objekt mit der Methode fill(Shape s)
gefüllt. Die aktuelle
Füllfarbe wird vorher mit setPaint(Paint p)
gesetzt.
Es kann sich hierbei um ein beliebiges Objekt handeln, welches das Paint
-Interface implementiert.
Als Stroking bezeichnet man das Zeichen der Umrißlinie eines Shape
-Objektes.
Das Zeichnen der Umrißlinie erfolgt anhand eines Stroke
-Objektes. Stroke
ist
ein Interface, daß Methoden vorschreibt, die ein konkreter Pinselstrich implementieren muß.
Das Zeichnen von Umrissen geschieht mit der Graphics2D
-Methode draw(Shape s)
.
Es wird der durch die Methode setStroke(Stroke s)
gesetzte Pinselstrich verwendet.
Als Farbe kommt auch hier die durch setPaint(Paint p)
gesetzte Farbe zur Verwendung.
Das Stroke-Interface definiert abstrakt einen Pinselstrich. Es schreibt lediglich eine Methode
vor:
public Shape createStrokedShape(Shape s)
.
Die Funktionsweise ist einfach nachzuvollziehen: Wenn die Umrißlinie eines Shape
-Objektes
gezeichnet werden soll, dann wird dieses Shape
-Objekt von Graphics2D
an createStrokedShape(Shape s)
übergeben. Graphics2D
erhält als Ergebnis ein Shape
-Objekt,
daß den Umriß mit fertig gezeichneter Umrißlinie darstellt.
Wenn z.B. ein Rechteck mit einer gestrichelten Umrißlinie gezeichnet werden soll, so wird
das Rechteck von Graphics2D
an die createStrokedShape(...)
-Methode der
jeweiligen Stroke
-Implemenation übergeben. Diese wird dann ein Shape
-Objekt zurückliefern,
dessen Umrißlinie in diesem Fall aus abwechselnd sichtbaren und unsichtbaren Liniensegmenten besteht -
einer gestrichelten Linie. createStrokedShape(...)
könnte z.B. auch dafür sorgen, daß
die Umrißlinie mit einer Dicke von 5 Pixeln gezeichnet wird oder daß der Umriß aus lauter
Dreiecken besteht.
Die Klasse java.awt.BasicStroke
ist eine konkrete Stroke
-Implementation.
Sie bietet folgende Funktionalität an:
BasicStroke
hat folgende Konstruktoren:
Konstruktor | Beschreibung |
---|---|
BasicStroke() |
konstruiert einen BasicStroke mit Default-Attributen |
BasicStroke(float width) |
konstruiert einen Default-BasicStroke mit der Breite width |
BasicStroke(float width, int cap, int join) |
konstruiert einen BasicStroke der Breite width ,
dem End Style cap und dem Join Style join .
Die Styles werden durch in der Klasse definierte Konstanten angegeben,
(s. folgendes Programmbeispiel)
|
BasicStroke(float width, int cap, int join, float joinlimit) |
konstruiert einen BasicStroke der Breite width ,
dem End Style cap , dem Join Style join
und einem Limit joinlimit in Pixeln für den angegeben
Join Style.
Die Styles werden durch in der Klasse definierte Konstanten angegeben,
(s. folgendes Programmbeispiel)
|
BasicStroke(float width, int cap, int join, float joinlimit, float[] dash, float dash_phase) |
wie vorheriger Konstruktor, aber mit einem Array dash , welches
das Muster (in Pixeleinheiten) für die Strichelung enthält (s. Beispiel).
dash_phase gibt an, daß bei der ersten Verwendung (und nur hier) von
dash vom ersten Array-Wert dash_phase Pixel subtrahiert
wird.
|
Die Verwendung von BasicStroke möchte ich anhand eines Beispieles aufzeigen. Hier werden
die Verschiedenen Join Styles anhand eines V-Förmigen GeneralPath
-Pfades demonstriert. Des
weiteren wird ein Rechteck mit der Strichelung "30 Pixel sichtbar, 10 Pixel unsichtbar,
5 Pixel sichtbar, 10 Pixel unsichtbar" gezeichnet. Als Zeichenfarbe kommt ein zyklischer
Farbverlauf von gelb nach lila zum Einsatz.
(Zugriff auf die Quelle):
public void paint(Graphics g) {
//Upcast --> mehr Funktionen in Graphics2D
Graphics2D g2d=(Graphics2D)g;
g2d.setPaint( new GradientPaint(20,50,new Color(255,241,9),
60,50,new Color(188,9,255),
true /*zyklischer Verlauf*/ )
);
//V-förmigen Shape erstellen:
GeneralPath vshape = new GeneralPath();
vshape.moveTo( 20, 50 );
vshape.lineTo( 50, 200 );
vshape.lineTo( 80, 50 );
//Pinselstriche mit allen möglichen Join- und Endstyles:
BasicStroke s1=new BasicStroke( 15, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL );
BasicStroke s2=new BasicStroke( 15, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_MITER );
BasicStroke s3=new BasicStroke( 15, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_ROUND );
//wiederholt:
// Pinselstrich setzen,Malen,Koordinatentranslation,...
g2d.setStroke(s1);
g2d.draw(vshape);
g2d.translate( 100, 0 );
g2d.setStroke(s2);
g2d.draw(vshape);
g2d.translate( 100, 0 );
g2d.setStroke(s3);
g2d.draw(vshape);
//Translation aufheben
g2d.setTransform( new AffineTransform() );
//---------------------------------------------------------
//Rechteck mit runden Ecken erzeugen
RoundRectangle2D dashedRect =
new RoundRectangle2D.Double( 20,250,500,200,40,40 );
float[] dash_array=new float[4];
dash_array[0]=30; //sichtbar
dash_array[1]=10; //unsichtbar
dash_array[2]=5; //sichtbar
dash_array[3]=10; //unsichtbar
BasicStroke s4 = new BasicStroke(
5f, //Breite
BasicStroke.CAP_SQUARE, //End Style
BasicStroke.JOIN_ROUND, //Join Style
1f, //Limit für Join
dash_array, //Strichelung
0 //offset in Pixeln f. Strichelung
);
g2d.setStroke( s4 ); //gestrichelter Pinselstrich setzen
g2d.draw( dashedRect ); //gestricheltes Rechteck malen
}
Das Ergebnis sieht wie folgt aus (mit Beschriftung):