vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Woche 2

Tag 9

Programme mit Grafik, Fonts und Farbe verfeinern

Die beste Möglichkeit, einen nichtprogrammierenden Bekannten zu beeindrucken, ist ein Programm, das Grafik verwendet. Onkel Walter wird wahrscheinlich die Nuancen einer wohlgeformten for-Schleife oder einer eleganten Klassenhierarchie nicht zu schätzen wissen; zeigen Sie ihm eine Animation mit einem Kleinkind, das den Ententanz aufführt, und er wird von Ihren Programmierfähigkeiten beeindruckt sein.

Heute beginnen Sie damit zu lernen, wie Sie Freunde gewinnen und Leute beeinflussen, indem Sie Applets schreiben, die Grafik, Fonts und Farbe verwenden.

Um grafische Features in einem Programm zu verwenden, benutzen Sie die Klassen des java.awt-Paketes, das die meisten der visuellen Möglichkeiten von Java liefert. Mit diesen Klassen geben Sie in einem Applet Text aus und zeichnen Figuren, wie z.B. Kreise und Polygone. Sie werden auch lernen, unterschiedliche Schriften und Farben für die Figuren, die Sie zeichnen, zu verwenden.

Sie werden auch anfangen, mit den verbesserten Zeichenmöglichkeiten von Java2D, einem Satz von Klassen, der mit Java 1.2 eingeführt wurde, zu arbeiten. Diese Klassen bieten einige bemerkenswerte Features:

Die Klasse Graphics

Sie können sich ein Applet als eine Leinwand für grafische Operationen vorstellen. Sie haben bereits die Methode drawString() verwendet, um Text in einem Applet auszugeben - man könnte auch sagen: den Text im Ausgabebereich des Applets zu zeichnen. Die Farbe und die Schriftart und die Farbe der Schrift wurden ausgewählt, bevor die einzelnen Zeichen ausgegeben wurden. Dies ist in etwa so wie bei einem Künstler, der die Farbe und den Pinsel wählt, bevor er mit dem Malen beginnt.

Text ist allerdings nicht das einzige, was Sie in einem Applet-Fenster zeichnen können. Sie können Linien, Ovale, Kreise, Bögen, Rechtecke und andere Polygone zeichnen.

Die meisten der elementaren Zeichenoperationen sind Methoden, die in der Klasse Graphics definiert sind. In einem Applet müssen Sie kein Objekt der Klasse Graphics erzeugen, um etwas zeichnen zu können - wie Sie sich vielleicht erinnern werden, wird der Methode paint() ein Objekt der Klasse Graphics als Parameter übergeben. Dieses Objekt repräsentiert das Applet-Fenster. Mit den Methoden dieses Objekts zeichnen Sie in das Applet-Fenster.

Die Graphics-Klasse ist Bestandteil des Paketes java.awt. Deshalb müssen alle Applets, die etwas zeichnen, über das import-Statement die Klasse Graphics in dem Programm verfügbar machen.

Listing 9.1 ist ein einfaches Applet, das mit der drawString()-Methode Text ausgibt, wie Sie das bereits zuvor in dem Palindrom-Applet gemacht haben.

Listing 9.1: Der Anfang von Map.java

1: import java.awt.Graphics;
2:
3: public class Map extends java.applet.Applet {
4: public void paint(Graphics screen) {
5:         screen.drawString("Florida", 185, 75);
6:     }
7: }

Dieses Applet verwendet die Methode drawString() des screen-Objekts, um den String »Florida« bei den Koordinaten 185,75 auszugeben. Listing 9.2 zeigt den HTML-Quelltext, über den das Applet angezeigt wird, nachdem es zu einer .class- Datei kompiliert wurde.

Listing 9.2: Der Quelltext von Map.html

1: <body bgcolor="#c4c4c4">
2: <div align="center">
3: <applet code="Map.class" height=350 width=350>
4: </applet>
5: </div>
6: </body>

In Abbildung 9.1 sehen Sie die Seite mit dem Applet im Netscape Navigator.


Abbildung 9.1:
Text im Applet-Fenster ausgeben

Alle der elementaren Zeichenbefehle, die Sie heute kennenlernen werden, sind Methoden der Klasse Graphics, die in der paint()-Methode eines Applets aufgerufen werden. Dies ist der ideale Ort für alle Zeichenoperationen, da paint() automatisch aufgerufen wird, sobald das Applet-Fenster neu dargestellt werden muß. Wenn z.B. das Fenster eines anderen Programms das Applet-Fenster verdeckt, muß das Applet- Fenster neu dargestellt werden, sobald das Fenster des anderen Programms verschoben wird. Indem Sie alle Zeichenoperationen in die paint()-Methode einfügen, stellen Sie sicher, daß kein Teil der Ausgabe beim Neuzeichnen übergangen wird.

Sie werden mit jeder neu behandelten Zeichenmethode das Map-Applet erweitern.

Das Koordinatensystem von Graphics

Wie bereits die drawString()-Methode haben alle Zeichenmethoden Argumente, die die x,y-Koordinaten für die jeweilige Aktion angeben. Manche erwarten mehr als ein Koordinaten-Paar. Dies ist z.B. bei Linien der Fall, bei denen ein x,y-Koordinatenpaar den Anfangspunkt angibt und ein anderes x,y-Koordinatenpaar den Endpunkt.

Javas Koordinatensystem verwendet Pixel als Maßeinheit. Der Koordinatenursprung (0,0) liegt in der oberen linken Ecke des Applet-Fensters. Die x-Werte wachsen nach rechts, ausgehend vom Ursprung, und die y-Werte wachsen nach unten. Dies unterscheidet sich von anderen Zeichensystemen, bei denen sich der Koordinatenursprung in der linken, unteren Ecke befindet und die y-Werte nach oben wachsen.

Alle Pixel-Werte sind Integer - Sie können keine Dezimalzahlen verwenden, um etwas zwischen den Integerwerten anzuzeigen.

Abbildung 9.2 illustriert Javas Grafikkoordinatensystem mit dem Ursprung 0,0. Zwei der Punkte des Rechtecks sind bei 20,20 und 60,60.


Abbildung 9.2:
Das Grafikkoordinatensystem von Java

Zeichnen und Füllen

Es stehen zwei Arten von Zeichenmethoden für viele der Figuren, die Sie in das Applet-Fenster zeichnen können: Methoden, deren Name mit draw beginnt und die nur den Umriß der jeweiligen Figur zeichnen, und Methoden, deren Name mit fill beginnt und die die jeweilige Figur mit der aktuellen Farbe füllen. Bei beiden Methodenarten wird der Umriß ebenso mit der aktuellen Farbe gezeichnet.


Sie können auch Bitmap-Dateien, wie z.B. GIF- oder JPEG-Dateien, ausgeben. Dazu verwenden Sie die Klasse Image. Darüber lernen Sie morgen mehr.

Linien

Die Methode drawLine() wird verwendet, um zwischen zwei Punkten eine Linie auszugeben. Die Methode erwartet vier Argumente: die x,y-Koordinaten des Startpunktes und die x,y-Koordinaten des Endpunktes:

drawLine(x1, y1, x2, y2);

Diese Methode zeichnet eine Linie von dem Punkt (x1, y1) zu dem Punkt (x2, y2). Die Breite der Linie ist mit einem Pixel festgelegt.

Fügen Sie die folgende Anweisung in die paint()-Methode des Map-Applets ein:

screen.drawLine(185,80,222,80);

Dies zeichnet eine Linie von 185,80 nach 222,80 - die Linie unterstreicht das Wort Florida im Applet-Fenster, wie das in Abbildung 9.3 zu sehen ist.


Abbildung 9.3:
Einfügen einer Linie in ein Applet


Um ein Schleudertrauma zu verhindern, das vom häufigen Hin- und Herspringen zwischen dem Text und Ihrem Java-Quellcode-Editor resultieren kann, ist der gesamte Quelltext am Ende dieses Abschnitts abgedruckt. Bis dahin können Sie sich auf den Text konzentrieren und später den gesamten Java-Code in einem Stück eingeben.

Rechtecke

Es gibt Graphics-Methoden für zwei Arten von Rechtecken: normale Rechtecke und Rechtecke mit abgerundeten Ecken (wie die Ecken der Tasten auf den meisten Computer-Tastaturen).

Um ein normales Rechteck zu zeichnen, verwenden Sie die Methode drawRect() (für den Umriß) und fillRect() (für ein gefülltes Rechteck).

Beide Methoden erwarten vier Argumente:

Fügen Sie die folgende Anweisung in das Map-Applet ein:

screen.drawRect(2, 2, 345, 345);

Dies fügt den Umriß eines Rechtecks ein, der sich fast an den Ecken des Applets befindet. Würden Sie hier die Methode fillRect() verwenden, würde ein ausgefülltes Rechteck gezeichnet werden, das einen Großteil der Applet-Fläche einnimmt und so den unterstrichenen Text Florida überdecken würde.

Rechtecke mit abgerundeten Ecken zeichnen Sie mit den Methoden drawRoundedRect() und fillRoundedRect(). Diese erwarten dieselben ersten vier Argumente, die auch die regulären Rechteck-Methoden erwarten. Zusätzlich sind noch zwei weitere Argumente am Ende der Parameterliste vorhanden.

Diese beiden letzten Argumente definieren die Breite und die Höhe des Bereiches, in dem die Ecken gerundet werden. Je größer dieser Bereich wird, desto runder werden die Ecken. Sie können ein Rechteck sogar wie einen Kreis oder ein Oval aussehen lasse, indem Sie diese Argumente groß genug machen.

Abbildung 9.4 zeigt einige Beispiele für Rechtecke mit abgerundeten Ecken. Ein Rechteck hat für die runden Ecken eine Breite von 30 und eine Höhe von 10. Ein anderes verwendet eine Breite von 20 und eine Höhe von 20 für die runden Ecken und sieht eher wie ein Kreis aus als wie ein Rechteck.


Abbildung 9.4:
Rechtecke mit abgerundeten Ecken

Fügen Sie die folgende Anweisung in die paint()-Methode des Map-Applets ein:

screen.drawRoundRect(182,61,43,24,10,8);

Hiermit zeichnen Sie ein Rechteck bei den Koordinaten 182,61 mit einer Breite von 43 Pixeln und einer Höhe von 24 Pixeln. Der rechteckige Bereich der runden Ecken ist 10 Pixel breit und 8 Pixel hoch. Das Ergebnis sehen Sie in Abbildung 9.5 - eine Art Nahaufnahme eines Teils des Applets.


Abbildung 9.5:
Hinzufügen eines Rechtecks in das Applet

Polygone

Polygone können mit den Methoden drawPolgon() und fillPolygon()gezeichnet werden.

Um ein Polygon zu zeichnen, müssen Sie für jeden Punkt des Polygons die x,y-Koordinaten angeben. Polygone können Sie sich als eine Reihe von Linien vorstellen, die an den Enden miteinander verbunden sind - eine Linie wird von einem Startpunkt zum Endpunkt gezeichnet. Dieser Endpunkt wird als Startpunkt für eine neue Linie verwendet und so weiter.

Sie können diese Koordinaten auf zweierlei Arten angeben:

Die zweite Methode ist wesentlich flexibler, da sie es ermöglicht, einzelne Punkte einem Polygon hinzuzufügen, bevor dieses gezeichnet wird.

Neben den x- und y-Koordinaten müssen Sie auch die Anzahl der Punkte in dem Polygon angeben. Sie können nicht mehr x,y-Koordinaten angeben, als Sie Punkte haben, bzw. Sie können auch nicht mehr Punkte angeben, als Sie Koordinatenpaare angeben. In beiden Fällen resultiert daraus ein Compiler-Fehler.

Beim Erzeugen eines Polygon-Objekts ist der erste Schritt, ein leeres Polygon mit der Anweisung new Polygon() wie folgt zu erstellen:

Polygon poly = new Polygon();

Als Alternative können Sie ein Polygon mit einer Reihe von Punkten, deren Koordinaten Sie in zwei Integer-Arrays angeben, erzeugen. Dafür ist es nötig, den Konstruktor Polygon(int[], int[], int) aufzurufen. Dabei geben Sie ein Array mit x-Werten und eines mit y-Werten und die Anzahl der Punkte an. Das folgende Beispiel verdeutlicht die Anwendung dieses Konstruktors:

int x[] = { 10, 20, 30, 40, 50 };
int y[] = { 15, 25, 35, 45, 55 };
int points = x.length;
Polygon poly = new Polygon(x, y, points);

Nachdem ein Polygon-Objekt erzeugt wurde, können Sie diesem Punkte hinzufügen. Dazu verwenden Sie die addPoint()-Methode des Objekts. Diese erwartet die x,y-Koordinaten des Punktes als Argument und fügt den Punkt dem Polygon hinzu. Im folgenden ein Beispiel:

poly.addPoint(60, 65);

Sobald ein Polygon-Objekt alle Punkte enthält, können Sie es mit der Methode drawPolygon() oder fillPolygon() zeichnen. Diese benötigen in diesem Fall nur ein Argument - das Polygon-Objekt, wie im folgenden gezeigt:

screen.drawPolygon(poly);

Wenn Sie die Methode drawPolygon() unter Java 1.02 verwenden, können Sie das Polygon schließen, indem Sie als letztes x,y-Koordinatenpaar das erste wiederholen. Andernfalls ist das Polygon an einer Seite offen.

Die Methode fillPolygon() schließt das Polygon automatisch, ohne daß ein übereinstimmender Anfangs- und Endpunkt nötig ist.


Das Verhalten von drawPolygon() änderte sich nach der Version 1.02 von Java. Bei der Version 1.1 und 1.2 schließt drawPolygon() automatisch ein Polygon, wie das bei fillPolygon() bereits der Fall war. Wenn Sie ein Polygon mit einer offenen Ecke mit diesen Versionen erstellen wollen, verwenden Sie die Methode drawPolyline(). Sie arbeitet genau wie drawPolygon() unter Java 1.02.

Fügen Sie die folgenden Anweisungen der paint()-Methode des Map-Applets hinzu, um Polygone in Aktion zu sehen:

int x[] = { 10, 234, 253, 261, 344, 336, 295, 259, 205, 211,
    195, 191, 120, 94, 81, 12, 10 };
int y[] = { 12, 15, 25, 71, 209, 278, 310, 274, 188, 171, 174,
    118, 56, 68, 49, 37, 12 };
int pts = x.length;
Polygon poly = new Polygon(x, y, pts);
screen.drawPolygon(poly);

Die Polygon-Klasse ist Bestandteil des Paketes java.awt. Aus diesem Grund müssen Sie sie verfügbar machen, indem Sie die folgende Anweisung am Beginn des Map-Applets einfügen:

import java.awt.Polygon;

Abbildung 9.6 zeigt, wie das mit dem Polygon Map-Applet aussieht, wenn alles andere bereits gezeichnet wurde.


Abbildung 9.6:
Hinzufügen eines Polygons in das Applet

Ovale

Die Methoden drawOval() und fillOval() werden verwendet, um Kreise und Ovale zu zeichnen.

Diese Methoden erwarten vier Argumente:

Da ein Oval keine Ecken hat, fragen Sie sich vielleicht, auf was sich die x,y-Koordinaten beziehen. Ovale werden auf die gleiche Weise gehandhabt wie die Rechtecke mit gerundeten Ecken. Die x,y-Koordinaten stellen die linke obere Ecke des rechteckigen Bereichs dar, in dem das Oval beschrieben ist.

Kehren Sie zum Map-Applet zurück, und fügen Sie die folgenden Anweisungen hinzu:

screen.fillOval(235,140,15,15);
screen.fillOval(225,130,15,15);
screen.fillOval(245,130,15,15);

Hier werden ausschließlich fill-Methoden anstelle der draw-Methoden verwendet. Deshalb entstehen drei schwarz gefüllte Kreise, die an einem Fleck in Zentral-Florida miteinander verbunden sind, wie das in Abbildung 9.7 zu sehen ist.


Abbildung 9.7:
Hinzufügen
dreier Kreise in das Applet

Bögen

Unter allen Zeichenmethoden sind Bögen die komplexesten bei der Konstruktion. Ein Bogen ist ein Teil eines Ovals und in Java als Bogen implementiert, der nur teilweise gezeichnet wird.

Bögen werden mit den Methoden drawArc() und fillArc() gezeichnet. Diese Methoden erwarten sechs Argumente:

Die ersten vier Argumente entsprechen denen für ein Oval und funktionieren auf dieselbe Art und Weise.

Der Startwinkel des Bogens reicht von 0 bis 359 Grad und wird gegen den Uhrzeigersinn gezählt. Auf einem Ziffernblatt einer Uhr würde 0 3 Uhr, 90 12 Uhr, 180 9 Uhr und 270 6 Uhr entsprechen.

Der Winkel, den ein Bogen überstreicht, reicht von 0 bis 359 Grad gegen den Uhrzeigersinn und von 0 bis -359 Grad im Uhrzeigersinn.

Abbildung 9.8 zeigt, wie die letzten beiden Argumente berechnet werden.


Abbildung 9.8:
Die Abmessungen eines Bogens ermitteln

Gefüllte Bögen werden so gezeichnet, als wären sie Stücke einer Torte. Anstatt die beiden Endpunkte miteinander zu verbinden, werden beide Endpunkte mit dem Mittelpunkt des Ovals des Bogens verbunden.

Im folgenden sehen Sie einen Beispiel für einen Aufruf der Methode drawArc():

screen.drawArc(20,25,315,150,5,-190);

Diese Anweisung zeichnet einen Bogen eines Ovals mit den Koordinaten 20,25, einer Breite von 315 Pixeln und einer Höhe von 190 Pixeln. Der Bogen beginnt bei der 5- Grad-Marke und überstreicht einen Winkel von 190 Grad im Uhrzeigersinn. Der Bogen wird in Abbildung 9.9 gezeigt.


Abbildung 9.9:
Ein Bogen

Als letzte Zutat für das Map-Applet werden wir eine Reihe kleiner Bögen zeichnen, die vier Argumente gemeinsam haben:

Die x,y-Koordinaten der Bögen ändern sich. Zwei for-Schleifen gehen dabei eine Reihe von x- und y-Werten durch.

Fügen Sie die beiden folgenden Anweisungen in die paint()-Methode des Map-Applets ein:

for (int ax = 50; ax < 150; ax += 10)
    for (int ay = 120; ay < 320 ; ay += 10)
        screen.drawArc(ax, ay, 10, 10, 0, -180);

Die Tatsache, daß sich hier zwei for-Schleifen ineinander befinden, mag auf den ersten Blick etwas verwirrend erscheinen. Im folgenden finden Sie deshalb die ersten sechs x,y-Koordinaten, die von den Schleifen erzeugt werden:

50,120
50,130
50,140
50,150
50,160
50,170

Wie Sie sehen, können, ändert sich die x-Koordinate - festgelegt durch ax - nicht. Diese ändert sich so lange nicht, bis die gesamte ay-Schleife durchgelaufen ist. Wenn dies geschehen ist, wird der Wert von ax um 10 erhöht und die ay-Schleife erneut komplett ausgeführt.

Kompilieren Sie das Map-Applet, um zu sehen, welchen Effekt diese Schleifen durch das Zeichnen einer ganzen Reihe kleiner Halbkreise produzieren. Listing 9.3 enthält den gesamten und endgültigen Quelltext für Map.java - inklusive aller Zeichenanweisungen, die in diesem Abschnitt behandelt wurden.

Listing 9.3: Der gesamte und endgültige Quelltext von Map.java

 1: import java.awt.Graphics;
 2: import java.awt.Polygon;
 3:
 4: public class Map extends java.applet.Applet {
 5:     public void paint(Graphics screen) {
 6:         screen.drawString("Florida", 185, 75);
 7:         screen.drawLine(185,80,222,80);
 8:         screen.drawRect(2, 2, 345, 345);
 9:         screen.drawRoundRect(182,61,43,24,10,8);
10:         int x[] = { 10, 234, 253, 261, 344, 336, 295, 259, 205, 211,
11:             195, 191, 120, 94, 81, 12, 10 };
12:         int y[] = { 12, 15, 25, 71, 209, 278, 310, 274, 188, 171, 174,
13:             118, 56, 68, 49, 37, 12 };
14:         int pts = x.length;
15:         Polygon poly = new Polygon(x, y, pts);
16:         screen.drawPolygon(poly);
17:         screen.fillOval(235,140,15,15);
18:         screen.fillOval(225,130,15,15);
19:         screen.fillOval(245,130,15,15);
20:         for (int ax = 50; ax < 150; ax += 10)
21:             for (int ay = 120; ay < 320 ; ay += 10)
22:                 screen.drawArc(ax, ay, 10, 10, 0, -180);
23:     }
24: }

Abbildung 9.10 zeigt das Map-Applet, das mit den elementaren Zeichenmethoden von Java gezeichnet wurde.


Abbildung 9.10:
Das Map-Applet

Obwohl kein Kartograph angesichts dieses Applets um die Sicherheit seines Arbeitsplatzes besorgt wäre, kombiniert dieses Applet Beispiele für die meisten Zeichen-Features, die unter Java über die Klasse Graphics zur Verfügung stehen. Ein Applet wie dieses kann über die Verwendung von Font- und Color-Objekten erweitert werden. Zusätzlich könnten die Zeichenoperationen neu arrangiert werden, um das Endprodukt zu verbessern.

Kopieren und Löschen

Die Graphics-Klasse bietet auch einiges an Cut-and-paste-Funktionalität, die das Applet-Fenster einbezieht:

Die Methode copyArea() erwartet sechs Argumente:

Die folgende Anweisung kopiert einen Bereich von 100 auf 100 Pixel in einen Bereich, der 50 Pixel rechts und 25 unterhalb davon liegt:

screen.copyArea(0,0,100,100,50,25);

Die Methode clearRect() erwartet dieselben vier Argumente wie die Methoden drawRect() und fillRect(). Die Methode füllt den angegebenen Bereich mit der aktuellen Hintergrundfarbe des Applets. Sie lernen später am heutigen Tag, wie Sie die Hintergrundfarbe festlegen.

Sie können die Größe des Fensters über die Methode size() ermitteln, wenn Sie das gesamte Applet-Fenster löschen wollen. Diese Methode gibt ein Dimensions-Objekt zurück. Die Variablen width und height dieses Objekts repräsentieren die Dimensionen des Applets. Die folgende Anweisung ist ein Beispiel für dieses Vorgehen:

screen.clearRect(0, 0, size().width, size().height);

Die size()-Methode wurde in den Java-Versionen nach 1.02 umbenannt. Sie funktioniert unter Java 1.2 weiterhin. Der Compiler gibt allerdings eine Warnung aus, daß diese Methode verworfen wurde. D.h. es ist eine neuere Methode verfügbar, die diese Methode ersetzt. Die Methode getSize() von Java 1.2 funktioniert genauso wie die size()-Methode. Die Änderung des Namens ist Teil der Anstrengungen von JavaSoft, eine konsistente Benennung der Methoden in der gesamten Klassenbibliothek von Java zu erreichen.

Text und Schriften

Die Objekte der Klasse java.awt.Font werden verwendet, um verschiedene Schriften für die Methode drawString() zur Verfügung zu haben. Font-Objekte repräsentieren den Namen, den Stil und die Punktgröße einer Schrift. Eine andere Klasse, FontMetrics , bietet Methoden, um die Größe der angezeigten Zeichen in der festgelegten Schrift zu ermitteln. Dies kann zur Formatierung und Zentrierung von Text verwendet werden.

Font-Objekte erzeugen

Ein Font-Objekt wird erzeugt, indem man den Konstruktor der Klasse mit drei Argumenten aufruft:

Der Name der Schrift kann ein bestimmter Schriftname, wie z.B. Arial oder Garamond Old Style sein. Diese Schrift wird verwendet, wenn die Schrift auf dem System, auf dem das Java-Programm ausgeführt wird, vorhanden ist.

Sie können auch die Namen der in Java integrierten Schriften verwenden: TimesRoman , Helvetica, Courier, Dialog und DialogInput.


In Java 1.1 und höher sollten die Schriftnamen TimesRoman, Helvetica und Courier durch serif, sanserif und monospaced ersetzt werden. Diese generischen Namen geben den Stil der Schrift an, ohne eine bestimmte Schriftfamilie festzulegen, die diesen repräsentiert. Dies stellt eine bessere Wahl dar, da manche Schriftfamilien nicht unter allen Java -Implementationen vorhanden sind. Auf diese Weise kann die Schrift ausgewählt werden, die auf der Plattform dem gewünschten Schriftstil (wie z.B. serif) am nächsten kommt.


Falls Sie das JDK unter Solaris 2.6 einsetzen, sollten Sie das SUNWi1of Paket für zusätzliche Latin-1 Schriften laden, da es ansonsten zu Warnungen beim Übersetzen kommen kann.

Es können drei verschiedene Schriftstile über die Konstanten Font.PLAIN, Font.BOLD und Font.ITALIC ausgewählt werden. Diese Konstanten sind Integer und können, um die Effekte zu kombinieren, addiert werden.

Das letzte Argument des Font()-Konstruktors ist die Größe der Schrift in Punkt.

Die folgende Anweisung erzeugt ein Font-Objekt der Schrift Dialog in 24-Punkt, fett und kursiv:

Font f = new Font("Dialog", Font.BOLD + Font.ITALIC, 24);

Zeichen und Strings ausgeben

Um die aktuelle Schrift festzulegen, wird die Methode setFont() der Graphics-Klasse verwendet. Als Argument wird dieser Methode ein Font-Objekt übergeben. Die folgende Anweisung verwendet ein Font-Objekt mit dem Namen ft:

screen.setFont(ft);

Text kann in einem Applet-Fenster mit der Methode drawString() ausgegeben werden. Diese Methode verwendet die aktuell ausgewählte Schrift. Wenn keine Schrift ausgewählt wurde, verwendet sie die Standardschrift. Mit der Methode setFont() können Sie jederzeit eine Schrift zur aktuellen Schrift machen.

Die folgende paint()-Methode erzeugt ein neues Font-Objekt, setzt dieses Objekt als die aktuelle Schrift und gibt den String "I'm very font of you." bei den Koordinaten 10,100 aus.

public void paint(Graphics screen) {
    Font f = new Font("TimesRoman", Font.PLAIN, 72);
    screen.setFont(f);
    screen.drawString("I'm very font of you.", 10, 100);
}

Informationen über Schriften ermitteln

Die Klasse FontMetrics kann zur Ermittlung detaillierter Informationen über eine Schrift, z.B. die Breite oder Höhe von Zeichen, die damit angezeigt werden können, verwendet werden.

Um die Methoden dieser Klasse zu verwenden, muß ein FontMetrics-Objekt mit der Methode getFontMetrics() erzeugt werden. Die Methode erwartet nur ein einziges Argument: ein Font-Objekt.

Tabelle 9.1 führt einige der Informationen auf, die Sie mit Hilfe der FontMetrics- Klasse ermitteln können. Alle diese Methoden sollten über ein FontMetrics-Objekt aufgerufen werden.

Methodenname

Beschreibung

stringWidth(String)

Gibt die gesamte Breite des übergebenen Strings in Pixeln zurück.

charWidth(char)

Gibt die Breite des übergebenen Zeichens zurück.

getHeight()

Gibt die Gesamthöhe der Schrift zurück.

Tabelle 9.1: Methoden der Klasse FontMetrics

Listing 9.4 zeigt, wie die Klassen Font und FontMetrics verwendet werden können. Das SoLong-Applet zeigt einen String in der Mitte des Applet-Fensters an. Mit Hilfe der FontMetrics-Klasse wird dazu die Breite des Strings in der aktuellen Schrift ermittelt.

Listing 9.4: Der gesamte Quelltext von SoLong.java

 1: import java.awt.Font;
 2: import java.awt.Graphics;
 3: import java.awt.FontMetrics;
 4:
 5: public class SoLong extends java.applet.Applet {
 6:
 7:     public void paint(Graphics screen) {
 8:         Font f = new Font("Courier", Font.BOLD, 18);
 9:         FontMetrics fm = getFontMetrics(f);
10:         screen.setFont(f);
11:         String s = "So long, and thanks for all the fish.";
12:         int x = (size().width - fm.stringWidth(s)) / 2;
13:         int y = size().height / 2;
14:         screen.drawString(s, x, y);
15:     }
16: }

Abbildung 9.11 zeigt zwei Kopien des SoLong-Applets auf einer Webseite. Jede weist eine andere Breite des Applet-Fensters auf.


Abbildung 9.11:
Zwei Kopien des SoLong- Applets

Die size()-Methode in den Zeilen 12 und 13 sollte durch die getSize()-Methode ersetzt werden, wenn Sie ein Applet für die Java-Version 1.1 oder höher schreiben. Die Größe des Applet-Fensters innerhalb des Applets zu ermitteln ist der Festlegung der exakten Größe im Applet vorzuziehen, da dies anpassungsfähiger ist. Sie können den HTML-Code der Webseite ändern, ohne das Programm ändern zu müssen, und es wird dennoch funktionieren.

Farbe

Die Klassen Color und ColorSpace des Paketes java.awt können Sie verwenden, um Ihre Applets bunter zu machen. Mit diesen Klassen können Sie die aktuelle Farbe für Zeichenoperationen sowie die Hintergrundfarbe für ein Applet und andere Fenster setzen. Sie haben auch die Möglichkeit, eine Farbe von einem Farbbeschreibungssystem in ein anderes zu konvertieren.

Standardmäßig verwendet Java Farben, die nach dem Farbbeschreibungssystem sRGB definiert sind. In diesem System wird eine Farbe über die Anteile der Farben Rot, Grün und Blau, die in ihr enthalten sind, definiert - hier kommt das R, G und B ins Spiel. Jede der drei Komponenten kann durch einen Integer-Wert zwischen 0 und 255 repräsentiert werden. Schwarz hat dann die Anteile 0,0,0 - sprich: es ist weder Rot noch Grün noch Blau vorhanden. Weiß dagegen hat die Anteile 255,255,255 - der Maximalwert aller drei Komponenten. sRGB-Werte lassen sich auch mit drei Fließkommazahlen darstellen, die jeweils einen Wert zwischen 0.0 und 1.0 haben. Java kann Millionen von Farben zwischen den beiden Extremwerten über sRGB erzeugen.

Ein Farbsystem wird in Java als Color Space (Farbraum) bezeichnet, und sRGB ist nur ein solcher Farbraum, der in einem Programm verwendet werden kann. Ein Ausgabegerät wie z.B. ein Monitor oder ein Drucker haben ihren eigenen Farbraum.

Wenn Sie etwas in einer bestimmten Farbe anzeigen oder drucken, kann es passieren, daß das Ausgabegerät diese Farbe nicht unterstützt. In diesem Fall wird entweder die Farbe durch eine andere Farbe substituiert, oder es wird ein Dither-Muster verwendet, um die nicht verfügbare Farbe anzunähern. Dies geschieht häufig im World Wide Web, wenn eine nicht verfügbare Farbe durch ein Dither-Muster aus zwei oder mehr Farben, die die fehlende Farbe annähern, ersetzt wird.

Die Realität des Farbmanagements in der Praxis sieht so aus, daß nicht alle Farben, die Sie über sRGB festlegen, auf allen Ausgabegeräten zur Verfügung stehen werden. Wenn Sie eine feinere Kontrolle über die Farbe benötigen, können Sie die Klasse ColorSpace und andere Klassen, die mit Java 1.2 eingeführt wurden, verwenden.

Für die meisten Programme wird das standardmäßig zur Definition von Farben verwendete sRGB völlig ausreichend sein.

Color-Objekte verwenden

Um die aktuelle Zeichenfarbe zu setzen, muß entweder ein Color-Objekt erzeugt werden, das die Farbe repräsentiert, oder Sie müssen eine der Standardfarben verwenden, die in der Color-Klasse verfügbar sind.

Es gibt zwei Möglichkeiten, den Konstruktor der Klasse Color aufzurufen, um eine Farbe zu erzeugen:

Sie können den sRGB-Wert einer Farbe entweder über drei int- oder drei float-Werte angeben. Die folgenden Anweisungen zeigen Beispiele hierfür:

Color c1 = new Color(0.807F,1F,0F);
Color c2 = new Color(255,204,102);

Das c1-Objekt beschreibt ein Neongrün und c2 eine in etwa karamelfarbige Farbe.


Es passiert sehr leicht, daß man Fießkomma-Literale, wie z.B. 0F oder 1F, mit Hexadezimalzahlen verwechselt, die an Tag 3 besprochen wurden. Farben werden häufig als Hexadezimalwerte angegeben, wie das z.B. beim Festlegen der Hintergrundfarbe im <BODY>-Tag einer HTML-Seite der Fall ist. Keine der Java-Klassen und -Methoden, mit denen Sie arbeiten, erwarten hexadezimale Argumente. D.h., wenn Sie Literale wie 0F oder 1F sehen, können Sie sicher sein, daß Sie es mit Fließkommazahlen zu tun haben.

Die aktuelle Farbe ermitteln und festlegen

Die aktuelle Farbe wird über die Methode setColor() der Klasse Graphics festgelegt. Diese Methode muß über das Graphics-Objekt aufgerufen werden, das den Bereich repräsentiert, in den Sie zeichnen. In einem Applet ist dies das Objekt, das der paint()-Methode übergeben wird.

Eine Möglichkeit, eine Farbe zu setzen, ist, eine der Standardfarben zu verwenden, die als Klassenvariablen der Klasse Color zu Verfügung stehen.

Diese Farben verwenden die folgenden Color-Variablen (die sRGB-Werte sind in Klammern dahinter angegeben):

Farbe

Variable

RGB-Wert

Schwarz

black

(0,0,0)

Blau

blue

(0,0,255)

Cyan

cyan

(0,255,255)

Dunkelgrau

darkGray

(64,64,64)

Grau

gray

(128,128,128)

Grün

green

(0,255,0)

Hellgrau

lightGray

(192,192,192)

Magenta

magenta

(255,0,255)

Orange

orange

(255,200,0)

Rosa

pink

(255,175,175)

Rot

red

(255,0,0)

Weiß

white

(255,255,255)

Gelb

yellow

(255,255,0)

Die folgende Anweisung setzt die aktuelle Farbe für das Screen-Objekt mit einer der Standard-Klassenvariablen:

screen.setColor(Color.pink);

Wenn Sie ein Color-Objekt erzeugt haben, kann es auf ähnliche Weise als aktuelle Farbe gesetzt werden:

Color brush = new Color(255,204,102);
screen.setColor(brush);

Nachdem Sie die aktuelle Farbe gesetzt haben, erscheinen alle Zeichenoperationen in dieser Farbe.

Sie können die Hintergrundfarbe bzw. die Vordergrundfarbe eines Applet-Fensters über die Methoden setBackground() bzw. setForeground() setzen. Diese Methoden erbt die Applet Klasse von einer ihrer Superklassen, so daß alle Applets, die Sie erzeugen, diese Methoden erben.

Die Methode setBackground() legt die Farbe des Hintergrundes des Applet-Fensters fest. Sie erwartet ein einziges Argument - ein Color-Objekt:

setBackground(Color.white);

Die Methode setForeground() wird über Komponenten der Benutzerschnittstelle und nicht über ein Graphics-Objekt aufgerufen. Sie arbeitet genauso wie die Methode setColor(), nur daß sie die Farbe einer Komponente, wie z.B. eine Schaltfläche oder ein Fenster, ändert.

Da ein Applet ein Fenster ist, können Sie die setForeground()-Methode in der init() -Methode verwenden, um die Farbe für Zeichenoperationen festzulegen. Diese Farbe wird so lange verwendet, bis eine andere Farbe entweder über setForeground() oder über setColor() gewählt wird.

Wenn Sie die aktuelle Farbe ermitteln wollen, können Sie die Methode getColor() über ein Graphics-Objekt aufrufen oder die Methoden getForeground() bzw. getBackground() der Applet-Klasse verwenden.

Die folgende Anweisung setzt die aktuelle Farbe des screen-Objekts - ein Objekt der Klasse Graphics - auf die Hintergrundfarbe des Applets:

screen.setColor(getBackground());

Fortgeschrittene Grafikoperationen mit Java2D

Eine der Erweiterungen, die Java 1.2 bietet, ist Java2D. Dabei handelt es sich um einen Satz von Klassen, die Ihnen 2D-Grafiken, Bilder und Text in hoher Qualität in Ihren Programmen ermöglichen. Die Java2D-Klassen erweitern die bestehenden Möglichkeiten der vorhandenen java.awt-Klassen, die zur Verarbeitung von Grafik verwendet werden - darunter auch die, die Sie heute kennengelernt haben. Sie ersetzen die vorhandenen Klassen allerdings nicht - Sie können die anderen Klassen und Programme, die diese implementieren, weiterhin verwenden.

Java2D hat unter anderem die folgenden Features:

Benutzer- und Gerätekoordinatensysteme

Eines der Konzepte, das mit Java2D eingeführt wurde, ist die Unterscheidung zwischen dem Kooerdinatensystem eines Ausgabegerätes und dem Koordinatensystem, auf das Sie sich beim Zeichnen eines Objekts beziehen.


Bisher wurde für alle Zeichenoperationen (dies gilt für alle Zeichenoperationen vor Java 1.2) nur das Gerätekoordinatensystem verwendet. Sie legen die x,y-Koordinaten auf einer Ausgabefläche wie z.B. einem Applet-Fenster fest. Diese Koordinaten wurden für das Zeichnen von Linien und anderen Elementen sowie die Ausgabe von Text verwendet.

Graphics2D-Objekte erzeugen

Die Zeichenoperationen, die Sie bisher erlernt haben, wurden über ein Graphics-Objekt aufgerufen, das den Ausgabebereich repräsentiert - z.B. ein Applet-Fenster. Für Java2D muß mit diesem Objekt ein neues Graphics2D-Objekt erzeugt werden, wie das in der folgenden paint()-Methode der Fall ist:

public void paint(Graphics screen) {
    Graphics2D screen2D = (Graphics2D)screen;
}

Das Objekt screen2D in diesem Beispiel wurde über Casting erzeugt. Es ist das screen-Objekt, das von einem Objekt der Graphics-Klasse in ein Objekt der Klasse Graphics2D konvertiert wurde.

Alle Java2D-Zeichenoperationen müssen über ein Graphics2D-Objekt aufgerufen werden. Graphics2D ist Bestandteil des Paketes java.awt.

Festlegen der Darstellungsattribute

Der nächste Schritt beim 2D-Zeichnen ist es, festzulegen, wie ein gezeichnetes Objekt dargestellt werden soll. Objekte, die nicht 2D sind, können nur ein Attribut wählen: die Farbe. 2D bietet eine breite Palette an Attributen, um die Farbe, die Linienstärke, Füllmuster, Transparenz und vieles mehr festzulegen.

2D Farben

Farben werden mit der Methode setColor() gesetzt. Dies funktioniert genauso wie mit der Graphics-Methode gleichen Namens. Im folgenden ein Beispiel:

screen2D.setColor(Color.black);

Obwohl einige der 2D-Methoden genauso wie deren Nicht-2D-Gegenstükke verwendet werden, müssen sie über ein Graphics2D-Objekt aufgerufen werden, um die Fähigkeiten von Java2D zu verwenden.

Java2D benötigt ein zweites Koordinatensystem, das Sie bei der Erzeugung - dem eigentlichen Zeichnen - verwenden. Dies wird als Benutzerkoordinatensystem bezeichnet.

Bevor irgendeine Zeichenoperation stattgefunden hat, befindet sich der Ursprung (die Koordinaten 0,0) des Benutzerkoordinatensystems und der des Gerätekoordinatensystems an der gleichen Stelle - der linken, oberen Ecke des Zeichenbereiches.

Der Ursprung des Benutzerkoordinatensystems kann als Ergebnis der ausgeführten 2D-Zeichenoperationen wandern. Als Folge einer 2D-Rotation können sogar die x- und y-Achse vertauscht werden. Sie lernen mehr über die beiden verschiedenen Koordinatensysteme, während Sie mit Java2D arbeiten.

Füllmuster

Füllmusterkontrollieren, wie ein gezeichnetes Objekt gefüllt wird. Mit Java2D können Sie eine Farbe, einen Verlauf, eine Textur oder ein Muster nach Ihren eigenen Vorstellungen verwenden.

Ein Füllmuster wird über die Methode setPaint() von Graphics2D definiert. Diese erwartet ein Paint-Objekt als einziges Argument. Die Paint-Schnittstelle wird von jeder Klasse implementiert, deren Objekte als Füllmuster verwendet werden können, darunter GradientPaint, TexturePaint und Color. Letzteres könnte Sie etwas überraschen. Allerdings ist die Verwendung eines Color-Objekts zusammen mit der setPaint() -Methode dasselbe, wie ein Objekt mit einer Farbe als Muster zu füllen.


Eine Verlaufsfüllung ist ein abgestufter Wechsel von einer Farbe an einem Koordinatenpunkt zu einer anderen Farbe an einem anderen Koordinatenpunkt. Der Wechsel kann zwischen den Punkten nur einmal geschehen, was als azyklischer Verlauf, oder wiederholt, was als zyklischer Verlauf bezeichnet wird.

Abbildung 9.12 zeigt Beispiele für azyklische und zyklische Verläufe zwischen Weiß und einer dunkleren Farbe. Die Pfeile weisen auf die Punkte, zwischen denen die Farben wechseln.


Abbildung 9.12:
Azyklische und zyklische Verläufe

Die Koordinatenpunkte in einem Verlauf beziehen sich nicht direkt auf Punkte des Graphics2D-Objekts, auf das gezeichnet wird. Statt dessen beziehen sich diese auf das Benutzerkoordinatensystem und können sogar außerhalb des Objekts, auf das gezeichnet wird, liegen.

Abbildung 9.13 illustriert dies. Beide Rechtecke in diesem Applet verwenden dasselbe GradientPaint-Objekt. Man kann sich ein Verlaufsfüllmuster als ein Stück Stoff vorstellen, das über eine ebene Oberfläche gespannt wird. Die Figuren, die mit einem Verlauf gefüllt werden, sind die Schnittmuster, die aus dem Stoff ausgeschnitten werden. Und aus einem Stück Stoff kann mehr als ein Muster ausgeschnitten werden.


Abbildung 9.13:
Zwei Rechtecke, die dasselbe GradientPaint-Objekt verwenden

Der Aufruf des GradientPaint-Konstruktors hat das folgende Format:

GradientPaint(x1,y1,color1,x2,y2,color2);

Der Punkt x1,y1 ist der Ort, an dem der Verlauf mit der Farbe color1 startet, und am Punkt x2,y2 endet der Verlauf mit der Farbe color2.

Wenn Sie einen zyklischen Verlauf wollen, ist ein zusätzliches Argument am Ende der Argumentenliste nötig:

GradientPaint(x1,y1,color1,x2,y2,color2,true);

Das letzte Argument ist ein boolescher Wert, der für einen zyklischen Verlauf true sein muß. Für azyklische Verläufe ist dieses Argument false. Sie können es aber auch ganz weglassen - azyklische Verläufe sind das Standardverhalten.

Nachdem Sie ein GradientPaint-Objekt erzeugt haben, legen Sie es als das aktuelle paint-Attribut über die Methode setPaint() fest. Die folgenden Anweisungen erzeugen und wählen einen Verlauf:

GradientPaint pat = new GradientPaint(0f,0f,Color.white,
    100f,45f,Color.blue);
screen2D.setPaint(pat);

Alle folgenden Zeichenoperationen, die auf das screen2D-Objekt angewendet werden, verwenden dieses Füllmuster, bis ein anderes festgelegt wird.

Strichstärke und Strichstil festlegen

Wie Sie bereits gelernt haben, haben die Linien aller Nicht-2D-Zeichenoperationen eine Stärke von einem Pixel. Java2D fügt die Möglichkeit hinzu, die Stärke der Zeichenlinie zu variieren. Dazu verwenden Sie die Methode setStroke() mit einem BasicStroke -Objekt als Argument.

Ein einfacher BasicStroke-Konstruktor erwartet drei Argumente:

Für die Argumente für den Stil des Linienendes und der Verbindungsstücke werden Variablen der Klasse BasicStroke verwendet. Die Einstellung für den Stil des Linienendes bezieht sich auf Linienenden, die nicht mit anderen Linien verbunden sind. Der Stil der Verbindungsstücke wird dagegen auf Linienenden angewendet, die mit anderen Linien verbunden sind.

Mögliche Stile für Linienenden sind CAP_BUTT, wenn keine Abschlußpunkte verwendet werden sollen, CAP_ROUND, wenn an beiden Enden Kreise angezeigt werden sollen, und CAP_SQUARE, wenn Quadrate zum Einsatz kommen sollen. In Abbildung 9.14 sind die einzelnen Stile für die Linienenden dargestellt. Wie Sie sehen können, ist der einzige sichtbare Unterschied zwischen den Stilen CAP_BUTT und CAP_SQUARE der, daß die Linie bei CAP_SQUARE aufgrund des Linienendes länger ist.


Abbildung 9.14:
Stile der Linienenden

Die möglichen Stile für die Verbindungsstücke sind JOIN_MITER, um Segmente zu verbinden, indem deren äußere Ecken erweitert werden, JOIN_ROUND, um die Ecke zwischen zwei Segmenten abzurunden, und JOIN_BEVEL, um die Segmente mit einer geraden Linie zu verbinden. Abbildung 9.15 zeigt Beispiele für jeden dieser Verbindungsstile.


Abbildung 9.15:
Verbindungstile für Liniensegmente

Die folgenden Anweisungen erzeugen ein BasicStroke-Objekt und setzen es als aktuelles Linienattribut:

BasicStroke pen = BasicStroke(2.0f,
    BasicStroke.CAP_BUTT,
    BasicStroke.JOIN_ROUND);
screen2D.setStroke(pen);

Die Linie hat eine Breite von zwei Pixeln, keine Abschlußpunkte und abgerundete Verbindungsstücke zwischen den Segmenten.

Objekte erzeugen

Nachdem Sie ein Graphics2D-Objekt erzeugt und die Darstellungsattribute festgelegt haben, sind die letzten zwei Schritte, ein Objekt zu erstellen und dieses zu zeichnen.

Gezeichnete Objekte werden in Java2D erzeugt, indem man eine geometrische Form mit den Klassen des Paketes java.awt.geom erstellt. Sie können all das, was Sie bereits zuvor in diesem Kapitel erstellt haben, inklusive Linien, Rechtecke, Ellipsen (Ovale), Bögen und Polygone, zeichnen.

Die Klasse Graphics2D verfügt nicht über unterschiedliche Methoden für die einzelnen Formen, die Sie zeichnen können. Statt dessen definieren Sie die Form und verwenden als Argument für die Methode draw() oder fill().

Linien

Linien werden mit der Klasse Line2D.Float erzeugt. Diese Klasse benötigt vier Argumente: die x,y-Koordinaten des einen Endpunktes, gefolgt von den x,y-Koordinaten des anderen Endpunktes. Im Anschluß ein Beispiel:

Line2D.Float ln = new Line2D.Float(60F,5F,13F,28F);

Diese Anweisung erzeugt eine Linie zwischen den Punkten 60,5 und 13,28. Beachten Sie, daß das F zu den Literalen gehört, die als Argumente übergeben werden - andernfalls würde der Compiler annehmen, daß es sich um Integer handelt.

Rechtecke

Rechtecke werden mit der Klasse Rectangle2D.Float oder Rectangle2D.Double erzeugt. Der Unterschied zwischen diesen beiden Klassen ist, daß die eine float-Argumente und die andere double-Argumente benötigt.

Rectangle2D.Float erwartet vier Argumente: die x-Koordinate, die y-Koordinate, die Breite und die Höhe. Im folgenden ein Beispiel:

Rectangle2D.Float rc = new Rectangle2D.Float(10F,13F,40F,20F);

Dies erzeugt ein Rechteck bei 10,13, das eine Breite von 40 Pixeln und eine Höhe von 20 Pixeln hat.

Ellipsen

Ovale Objekte werden in Java2D als Ellipsen bezeichnet und mit der Klasse Ellipse2d.Float erstellt. Dafür sind vier Argumente nötig: die x-Koordinate, die y- Koordinate, die Breite und die Höhe.

Die folgende Anweisung erzeugt eine Ellipse bei 113,25 mit einer Breite von 22 Pixeln und einer Höhe von 40 Pixeln:

Ellipse2D.Float ee = new Ellipse2D.Float(113,25,22,40);

Bögen

Bögen werden mit der Klasse Arc2D.Float erzeugt. Dies läuft ganz ähnlich wie bei den Nicht-2D-Gegenstücken, nur daß es hier ein zusätzliches Feature gibt: Sie können angeben, wie der Bogen geschlossen wird.

Arc2D.Float erwartet sieben Argumente. Die ersten vier definieren die Ellipse, von der der Bogen ein Teil ist: die x-Koordinate, die y-Koordinate, die Breite und die Höhe. Die letzten drei Argumente sind der Startwinkel, die vom Bogen überstrichene Gradzahl und ein Integer, der festlegt, wie der Bogen geschlossen wird.

Der vom Bogen überstrichene Winkel wird im Uhrzeigersinn mit positiven Zahlen angegeben. Dies steht im Gegensatz zu der Art, wie Nicht-2D-Bögen verarbeitet werden.

Das letzte Argument verwendet eine von drei Klassenvariablen: Arc2D.OPEN für einen nicht geschlossenen Bogen, Arc2D.CHORD, um die Endpunkte des Bogens mit einer geraden Linie zu verbinden, und Arc2D.PIE, um die Endpunkte des Bogens mit dem Mittelpunkt der Ellipse zu verbinden, wie das bei einem Tortenstück der Fall ist. In Abbildung 9.16 sind die verschiedenen Stile gezeigt.


Abbildung 9.16:
Verschiedene Stile zum Schließen von Bögen


Der Stil Arc2D.OPEN läßt sich nicht auf gefüllte Bögen anwenden. Ein gefüllter Bogen, der den Stil Arc2D.OPEN verwendet, wird mit dem Stil Arc2D.CHORD geschlossen.

Die folgende Anweisung erzeugt ein Arc2D.Float-Objekt:

Arc2D.Float = new Arc2D.Float(27,22,42,30,33,90,Arc2D.PIE);

Dies erzeugt einen Bogen für ein Oval bei 27,22 mit einer Breite von 42 Pixeln und einer Höhe von 30 Pixeln. Der Bogen beginnt bei 33 Grad, überstreicht 90 Grad und wird wie ein Tortenstück geschlossen.

Polygone

Polygone werden unter Java2D erzeugt, indem man jeden einzelnen Schritt von einem Punkt eines Polygons zum nächsten definiert. Ein Polygon kann aus geraden Linien, quadratischen Kurven und Bézier-Kurven geformt werden.

Die einzelnen Schritte für die Erzeugung eines Polygons werden als GeneralPath- Objekt erstellt. Diese Klasse ist ebenfalls Bestandteil des Paketes java.awt.geom.

Ein GeneralPath-Objekt kann ohne Argumente erzeugt werden, wie das im folgenden gezeigt wird:

GeneralPath polly = new GeneralPath();

Die Methode moveTo() der Klasse GeneralPath wird zur Erzeugung des ersten Punktes des Polygons verwendet. Die folgende Anweisung würde verwendet werden, wenn Sie das Polygon bei dem Punkt 5,0 beginnen lassen wollten:

polly.moveTo(5f, 0f);

Nachdem Sie den ersten Punkt erzeugt haben, verwenden Sie die Methode lineTo(), um Linien zu erzeugen, die bei einem neuen Punkt enden. Diese Methode benötigt zwei Argumente: die x- und y-Koordinate des neuen Punktes.

Die folgenden Anweisungen fügen dem polly-Objekt drei neue Linien hinzu:

polly.lineTo(205f, 0f);
polly.lineTo(205f, 90f);
polly.lineTo(5f, 90f);

Die Methoden lineTo() und moveTo() benötigen float-Argumente für die Koordinatenangabe.

Wenn Sie ein Polygon schließen wollen, verwenden Sie die Methode closePath(). Diese wird ohne Argumente aufgerufen, wie im folgenden gezeigt:

polly.closePath();

Diese Methode schließt ein Polygon, indem sie den aktuellen Punkt mit dem Punkt, der bei dem letzten Aufruf der moveTo()-Methode angegeben wurde, verbindet. Sie können ein Polygon auch ohne Aufruf dieser Methode schließen, indem Sie mit der lineTo()-Methode eine Linie zum Ausgangspunkt ziehen.

Sobald Sie ein offenes oder ein geschlossenes Polygon erzeugt haben, können Sie es wie jede andere Figur mit der draw()- oder der fill()-Methode zeichnen. Das polly- Objekt ist ein Rechteck mit den Punkten (5,0), (205,0), (205,90) und (5,90).

Objekte zeichnen

Nachdem Sie die Darstellungsattribute, wie z.B. Farbe und Strichstärke, festgelegt und ein Objekt, das gezeichnet werden soll, erstellt haben, sind Sie bereit, etwas in aller 2D-Pracht zu zeichnen.

Alle gezeichneten Objekte verwenden dieselbe Methode der Klasse Graphics2D: draw() für Umrisse und fill() für gefüllte Objekte. Beide erwarten als einziges Argument ein Objekt.

Strings werden unter Java2D mit der Methode drawString() ausgegeben. Diese erwartete drei Argumente: das auszugebende String-Objekt und dessen x,y-Koordinaten. Wie auch alle anderen Koordinaten in Java2D müssen hier Fließkommazahlen anstelle von Integern angegeben werden.

Ein Java2D-Beispiel

Etwas früher am heutigen Tag haben Sie ein Karte von Florida mit den Zeichenmethoden, die in der Graphics-Klasse zur Verfügung stehen, erstellt. Das nächste Applet, das Sie erzeugen werden, erstellt eine überarbeitete Version dieser Karte, die 2D-Zeichentechniken verwendet.

Da alle Klassen von Java2D in der Version 1.2 von Java neu eingeführt wurden, kann dieses Applet nur mit einem Web Browser angezeigt werden, der Java 1.2 unterstützt. Beim Schreiben des Buches ist der Applet-Viewer, der dem JDK 1.2 beiliegt, die einzige Möglichkeit, dieses Applet anzuzeigen.

Listing 9.5 beinhaltet das Map2D-Applet. Es ist ein längeres Programm, als das bei vielen anderen Programmen in diesem Buch der Fall ist, da 2D mehr Anweisungen benötigt, um Zeichenoperationen umzusetzen.

Listing 9.5: Der gesamte Quelltext von Map2D.java

 1: import java.awt.*;
 2: import java.awt.geom.*;
 3:
 4: public class Map2D extends java.applet.Applet {
 5:     public void paint(Graphics screen) {
 6:         Graphics2D screen2D = (Graphics2D)screen;
 7:         setBackground(Color.blue);
 8:         // Zeichne Wellen
 9:         screen2D.setColor(Color.white);
10:         BasicStroke pen = new BasicStroke(2F,
11:             BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
12:         screen2D.setStroke(pen);
13:         for (int ax = 10; ax < 340; ax += 10)
14:             for (int ay = 30; ay < 340 ; ay += 10) {
15:                 Arc2D.Float wave = new Arc2D.Float(ax, ay,
16:                     10, 10, 0, 180, Arc2D.OPEN);
17:                 screen2D.draw(wave);
18:             }
19:         // Zeichne Florida
20:         GradientPaint gp = new GradientPaint(0F,0F,Color.green,
21:             50F,50F,Color.orange,true);
22:         screen2D.setPaint(gp);
23:         GeneralPath fl = new GeneralPath();
24:         fl.moveTo(10F,12F);
25:         fl.lineTo(234F,15F);
26:         fl.lineTo(253F,25F);
27:         fl.lineTo(261F,71F);
28:         fl.lineTo(344F,209F);
29:         fl.lineTo(336F,278F);
30:         fl.lineTo(295F,310F);
31:         fl.lineTo(259F,274F);
32:         fl.lineTo(205F,188F);
33:         fl.lineTo(211F,171F);
34:         fl.lineTo(195F,174F);
35:         fl.lineTo(191F,118F);
36:         fl.lineTo(120F,56F);
37:         fl.lineTo(94F,68F);
38:         fl.lineTo(81F,49F);
39:         fl.lineTo(12F,37F);
40:         fl.closePath();
41:         screen2D.fill(fl);
42:         // Zeichne Ovale
43:         screen2D.setColor(Color.black);
44:         BasicStroke pen2 = new BasicStroke();
45:         screen2D.setStroke(pen2);
46:         Ellipse2D.Float e1 = new Ellipse2D.Float(235,140,15,15);
47:         Ellipse2D.Float e2 = new Ellipse2D.Float(225,130,15,15);
48:         Ellipse2D.Float e3 = new Ellipse2D.Float(245,130,15,15);
49:         screen2D.fill(e1);
50:         screen2D.fill(e2);
51:         screen2D.fill(e3);
52:     }
53: }

Um dieses Applet anzuzeigen, müssen Sie ein kurze HTML-Datei dafür erstellen (siehe Listing 9.6). Da dieses Applet Java-1.2-Klassen und -Methoden verwendet, kann es nur mit einem Browser angezeigt werden, der diese Version der Sprache unterstützt. Um sicherzugehen, sollten Sie den Applet-Viewer des JDK 1.2 verwenden. Der Applet-Viewer verarbeitet das <APPLET>-Tag und ignoriert alle anderen HTML-Tags. Es besteht also kein Grund, eine komplexe HTML-Seite zu erstellen, wenn Sie etwas mit diesem Tool anzeigen wollen.

Listing 9.6: Der gesamte Quelltext von Map2D.html

1: <applet code="Map2D.class" height=370 width=350>
2: </applet>

Einige Beobachtungen zu dem Map2D-Applet:

Abbildung 9.17 zeigt die Ausgabe des Map2D-Applets im Applet-Viewer.


Abbildung 9.17:
Das Map2D-Applet

Zusammenfassung

Sie verfügen nun über einige Tools, mit denen Sie das Erscheinungsbild eines Applets verbessern können. Sie können mit Linien, Rechtecken, Ellipsen, Polygonen, Schriften, Farben und Mustern auf einem Applet-Fenster arbeiten, indem Sie Nicht-2D- und 2D-Klassen verwenden.

Bei Nicht-2D-Zeichenoperationen verwenden Sie Methoden der Klasse Graphics mit Argumenten, die das zu zeichnende Objekt beschreiben.

Java2D verwendet für jede Zeichenoperation dieselben beiden Methoden - draw() und fill(). Unterschiedliche Objekte werden mit den Klassen aus dem Paket java.awt.geom erzeugt. Diese werden dann als Argumente für die Zeichenmethoden von Graphics2D verwendet.

Später in diesem Buch lernen Sie, wie Sie auf andere Komponenten eines Java-Programms in der Art, wie Sie es mit dem Applet-Fenster getan haben, zeichnen. Dies ermöglicht es Ihnen, die Techniken des heutigen Tages auch in Java-Applikationen zu verwenden.

Sie werden morgen noch mehr Gelegenheit erhalten, Onkel Walter zu beeindrucken, wenn der Kunstunterricht Animation und die Anzeige von Bilddateien behandelt.

Fragen und Antworten

Frage:
Ich will eine Textzeile ausgeben, in deren Mitte sich ein fett gedrucktes Wort befindet. Ich verstehe, daß ich zwei verschiedene Font-Objekte dafür brauche - eines für die normale Schrift und eines für die fette - und daß ich die aktuelle Schrift mittendrin umdefinieren muß. Das Problem ist nun, daß drawString() eine x- und eine y-Position für den Beginn eines jeden Strings benötigt, und ich kann nichts finden, was sich auf die aktuelle Position innerhalb des Applet-Fensters bezieht. Wie kann ich ermitteln, wo das fett gedruckte Wort starten soll?.

Antwort:
Die Darstellungsmöglichkeiten von Java für Text sind ziemlich primitiv. Java hat nichts in der Art eines aktuellen Punktes, so daß Sie selbst ermitteln müssen, wo sich das Ende des einen Strings befindet, um den nächsten String zu beginnen. Die Methode stringWidth() kann Ihnen bei diesem Problem helfen - sowohl, um die Länge des gerade ausgegebenen Strings zu ermitteln, als auch, um Leerraum danach einzufügen.



vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Ein Imprint des Markt&Technik Buch- und Software-Verlag GmbH.
Elektronische Fassung des Titels: Java 2 in 21 Tagen, ISBN: 3-8272-5578-3