Grafiken, Fonts und Farben
von Laura Lemay
Sie wissen jetzt, wie Applets funktionieren. In den übrigen Lektionen dieser Woche lernen Sie, was man mit Applets, die Objekte aus der Java-Klassenbibliothek enthalten, alles machen kann, und wie sie kombiniert werden, um interessante Effekte zu erzeugen. Sie beginnen heute mit dem Zeichnen am Bildschirm, d. h. wie Linien und Formen mit den einfachen integrierten Grafikobjekten erstellt werden, wie Text in verschiedenen Schriftarten ausgegeben wird und wie Farben in Applets verwendet und geändert werden. Heute lernen Sie insbesondere:
Mit den Grafikfähigkeiten von Java können Sie Linien, Formen, Zeichen und Bilder in einem Applet am Bildschirm ausgeben. Grafikoperationen sind in Java größtenteils Methoden, die in der Graphics-Klasse definiert sind. Sie brauchen keine Instanz von Graphics zu erstellen, um etwas in einem Applet zu zeichnen. In der paint()-Methode Ihres Applets (die Sie gestern gelernt haben) erhalten Sie automatisch ein Graphics-Objekt. Durch Zeichnen in diesem Objekt zeichnen Sie in Ihrem Applet und die Ergebnisse erscheinen am Bildschirm.
Die Graphics-Klasse ist Teil des Pakets java.awt. Wenn Sie also etwas in Ihrem Applet zeichnen (was absolut üblich ist), stellen Sie sicher, daß Sie diese Klasse am Anfang der Java-Datei importieren:
import java.awt.Graphics; public class MyClass extended java.applet.Applet { ... }
Um ein Objekt am Bildschirm zu zeichnen, rufen Sie eine der in der Graphics-Klasse verfügbaren Zeichnungsmethoden auf. Alle Zeichnungsmethoden haben Argumente, die Endpunkte, Ecken und Anfangspunkte des Objekts als Werte im Applet-Koordinatensystem darstellen. So beginnt eine Linie beispielsweise an den Punkten 10,10 und endet an den Punkten 20,20.
Der Ausgangspunkt (0,0) des Java-Koordinatensystems ist die obere linke Ecke. Positive x-Werte sind rechts und positive y-Werte sind unten. Alle Pixelwerte sind Ganzzahlen. Es gibt keine teilweisen Pixel. Abb. 9.1 zeigt, wie ein einfaches Viereck anhand dieses Koordinatensystems gezeichnet werden kann.
Abbildung 9.1: Das Java-Grafikkoordinatensystem
Javas Koordinatensystem unterscheidet sich von vielen Zeichen- und Layoutprogrammen, deren x und y in der unteren linken Ecke liegen. Falls Sie nicht daran gewöhnt sind, mit diesem praktisch umgekehrten Grafiksystem zu arbeiten, können Sie ein wenig damit üben.
Die Graphics-Klasse enthält verschiedene einfache Grafikelemente zum Zeichnen, darunter Linien, Rechtecke, Vielecke, Ovale und Bögen.
Um gerade Linien zu zeichnen, benutzen Sie die Methode drawLine. drawLine nimmt vier Argumente an: Die x- und y-Koordinaten des Anfangs- und des Endpunkts.
public void paint(Graphics g) { g.drawLine(25,25,75,75); }
Abbildung 9.2: Linien zeichnen
Die in Java enthaltenen Grafikelemente bieten drei verschiedene Arten von Rechtecken:
Für jede dieser Rechteckarten stehen zwei Methoden zur Wahl: Eine, die das Rechteck in Konturenform und eine, die es mit Füllfarbe zeichnet.
Um ein einfaches Rechteck zu zeichnen, verwenden Sie die Methode drawRect oder fillRect. Beide haben vier Argumente: die x- und y-Koordinaten der oberen linken Ecke und die Breite und Höhe des Rechtecks. Folgende paint()-Methode zeichnet z. B. zwei Vierecke: links eine Kontur und rechts ein gefülltes Viereck (siehe Abb. 9.3):
public void paint(Graphics g) { g.drawRect(20,20,60,60); g.fillRect(120,20,60,60); }
Zum Zeichnen von Rechtecken mit gerundeten Ecken benutzen Sie die Methode drawRoundRect oder fillRoundRect, wobei die zweite ein Rechteck mit gerundeten Ecken und Füllfarbe erzeugt. Dies entspricht den einfachen Rechtecken, mit dem Unterschied, daß hier zwei zusätzliche Argumente für die Breite und Höhe des Winkels der gerundeten Ecken erforderlich sind. Diese zwei Argumente bestimmen, in welchem Bogen entlang der Rechteckkanten gezeichnet wird. Das erste Argument bestimmt den Winkel auf der horizontalen und das zweite den auf der vertikalen Ebene. Größere Werte für die Winkelbreite und -höhe lassen das Rechteck insgesamt stärker gerundet erscheinen. Werte, die der Breite und Höhe des Rechtecks entsprechen, erzeugen einen Kreis. Einige Beispiele mit gerundeten Ecken sind in Abb. 9.4 ersichtlich.
Die folgende paint-Methode zeichnet zwei gerundete Rechtecke, eines als Kontur mit einer gerundeten Ecke von 10 Pixel im Quadrat und eines gefüllt mit einer gerundeten Ecke von 20 Pixel im Quadrat (Abb. 9.5 zeigt die sich daraus ergebenden Formen):
public void paint(Graphics g) { g.drawRoundRect(20,20,60,60,10,10); g.fillRoundRect(120,20,60,60,20,20); }
Abbildung 9.5: Gerundete Rechtecke
Die dreidimensionalen Rechtecke sind eigentlich nicht dreidimensional. Sie haben vielmehr eine Schattierung, die den Eindruck vermittelt, daß sich das Rechteck vom Hintergrund abhebt. Dreidimensionale Rechtecke haben vier Argumente: für die x- und y-Anfangsposition sowie für die Breite und Höhe des Rechtecks. Das fünfte ist ein boolesches Argument und bestimmt, ob durch den dreidimensionalen Effekt das Rechteck vertieft (true) oder erhaben (false) ist. Wie bei den anderen Rechteckarten gibt es auch verschiedene Methoden zum Zeichnen und Füllen: draw3DRect und fill3DRect. Der folgende Code produziert zwei solche Rechtecke - das linke ist erhaben und das rechte vertieft (die Ergebnisse sind in Abb. 9.6 ersichtlich):
public void paint(Graphics g) { g.draw3DRect(20,20,60,60,true); g.draw3DRect(120,20,60,60,false); }
Abbildung 9.6: Dreidimensionale Rechtecke
Vielecke sind Formen mit einer unbegrenzten Zahl von Kanten. Um ein Vieleck (Polygon) zu zeichnen, brauchen Sie mehrere x- und y-Koordinaten. Die Zeichnungsmethode beginnt bei Eins und zeichnet eine Linie bis zur zweiten, dritten und allen übrigen Koordinaten.
Wie bei Rechtecken können Sie ein konturiertes oder gefülltes Vieleck zeichnen (die Methode dafür ist drawPolygon bzw. fillPolygon). Außerdem können Sie die Koordinaten als Reihen von x- und y-Koordinaten oder als Instanz der Polygon-Klasse festlegen.
Beim ersten Verfahren haben die Methoden drawPolygon und fillPolygon drei Argumente:
Die x- und y-Reihen sollten selbstverständlich die gleiche Zahl von Elementen haben.
Im folgenden Beispiel wird ein konturiertes Vieleck mit diesem Verfahren gezeichnet (das Ergebnis ist in Abb. 9.7 dargestellt):
public void paint(Graphics g) { int exes[] = { 39,94,97,142,53,58,26 }; int whys[] = { 33,74,36,70,108,80,106 }; int pts = exes.length; g.drawPolygon(exes,whys,pts); }
Abbildung 9.7: Einfaches Vieleck (Kontur)
Beachten Sie, daß Java ein konturiertes Vieleck nicht automatisch schließt. Wenn Sie eine geschlossene Form wollen, müssen Sie den Anfangspunkt des Vielecks am Ende der Reihe einfügen. Wenn Sie ein gefülltes Vieleck zeichnen, werden die Anfangs- und Endpunkte geschlossen.
Beim zweiten Verfahren des Aufrufens von drawPolygon und fillPolygon wird ein Polygon-Objekt verwendet. Die Polygon-Klasse ist nützlich, wenn Sie beabsichtigen, Punkte in das Vieleck einzufügen oder das Vieleck spontan zu erstellen. Die Polygon-Klasse ermöglicht Ihnen, das Vieleck als Objekt, nicht als einzelne Reihen zu behandeln.
Um ein Vieleckobjekt zu erstellen, legen Sie ein leeres Vieleck an:
Polygon poly = new Polygon();
Alternativ erstellen Sie ein Vieleck aus mehreren Punkten anhand von Ganzzahlenreihen, wie im vorherigen Beispiel:
int exes[] = { 39,94,97,142,53,58,26 }; int whys[] = { 33,74,36,70,108,80,106 }; int pts = exes.length; Polygon poly = new Polygon(exes, whys,pts);
Nachdem Sie ein Vieleckobjekt erstellt haben, können Sie es um die benötigten Punkte erweitern:
poly.addPoint(20,35);
Zum Zeichnen des Vielecks verwenden Sie das Vieleckobjekt als Argument für drawPolygon oder fillPolygon. Im folgenden Beispiel wurde der obige Code mit einem Polygon-Objekt geschrieben. Außerdem ist dieses Vieleck auch gefüllt (die Ausgabe ist in Abb. 9.8 dargestellt):
public void paint(Graphics g) { int exes[] = { 39,94,97,142,53,58,26 }; int whys[] = { 33,74,36,70,108,80,106 }; int pts = exes.length; Polygon poly = new Polygon(exes, whys,pts); g.fillPolygon(poly); }
Abbildung 9.8: Gefülltes Vieleck
Mit Ovalen können Sie Ellipsen oder Kreise zeichnen. Ovale sind wie Rechtecke mit übermäßig gerundeten Ecken. Im Grunde werden sie mit den gleichen vier Argumenten gezeichnet: x und y für die obere Ecke sowie Breite und Höhe des Ovals. Der Anfangspunkt befindet sich aber links oben in einiger Entfernung von der tatsächlichen Kontur des Ovals. Wenn Sie sich das Oval als Rechteck vorstellen, können Sie es leichter anordnen.
Wie bei den anderen Zeichnungsoperationen zeichnet die drawOval-Methode eine Kontur eines Ovals, während die Methode fillOval ein gefülltes Oval erzeugt.
Im folgenden Beispiel werden zwei Ovale - ein Kreis und eine Ellipse - gezeichnet (wie diese Formen am Bildschirm aussehen, ist in Abb. 9.9 dargestellt):
public void paint(Graphics g) { g.drawOval(20,20,60,60); g.fillOval(120,20,100,60); }
Abbildung 9.9: Beispiele von Ovalen
Von allen Zeichnungsoperationen sind Bögen die komplexesten, deshalb habe ich sie bis zuletzt aufgehoben. Ein Bogen ist ein Teil eines Ovals. Am leichtesten kann man sich einen Bogen als Hälfte eines kompletten Ovals vorstellen. Abb. 9.10 zeigt einige Beispiele von Bögen.
Die drawArc-Methode erhält sechs Argumente: Anfangsecke, Breite und Höhe, den Winkel, in dem der Bogen beginnt, und die Grade, in denen er bis zum Ende gezeichnet wird. Auch hier zeichnet die drawArc-Methode die Kontur eines Bogens und fillArc einen gefüllten Bogen. Gefüllte Bögen werden als Abschnitte eines Kreises gezeichnet. Anstelle des Zusammenfügens der zwei Endpunkte werden beide Endpunkte in der Kreismitte zusammengefügt.
Wichtig ist zu wissen, daß ein Bogen im Prinzip als Oval formuliert und dann nur teilweise gezeichnet wird. Die Anfangsecke sowie die Breite und Höhe sind nicht der Anfangspunkt und die Breite und Höhe des eigentlichen Bogens, wie er am Bildschirm dargestellt wird, sondern der vollen Ellipse, aus der der Bogen besteht. Diese ersten Punkte bestimmen G röße und Form des Bogens. Die zwei letzteren Argumente (für die Grade) bestimmen die Anfangs- und Endpunkte.
Wir beginnen mit einem einfachen Bogen - einer C-Form (siehe Abb. 9.11).
Um die Methode zum Zeichnen dieses Bogens zu bilden, stellen Sie sich den Bogen zunächst als kompletten Kreis vor. Dann ermitteln Sie die x- und y-Koordinaten sowie die Breite und Höhe des Kreises. Diese vier Werte sind die ersten vier Argumente für die drawArc- bzw. fillArc-Methode. Abb. 9.12 zeigt, wie diese Werte von dem obigen C-Bogen ermittelt werden.
Abbildung 9.12: Bilden eines kreisrunden Bogens
Um die letzten zwei Argumente zu ermitteln, stellen Sie sich den Kreis in Graden vor. Null Grad ist bei 3 Uhr, 90 Grad bei 12 Uhr, 180 Grad bei 9 Uhr und 270 Grad bei 6 Uhr. Der Anfang des Bogens ist der Gradwert des Bogenanfangs. In diesem Beispiel ist der Anfangspunkt am oberen C-Ende bei 90 Grad; 90 ist also das fünfte Argument.
Das sechste und letzte Argument ist ein anderer Gradwert, der bezeichnet, wie weit sich der Kreis schwingt und in welche Richtung er geht (das ist nicht der endende Gradwinkel). Da es sich in diesem Fall um einen halben Kreis handelt, schwingt der Bogen um 180 Grad. Somit ist 180 das letzte Argument des Bogens. Hier schwingt der Bogen 180 Grad entgegen dem Uhrzeigersinn, was in Java der positiven Richtung entspricht. Falls Sie ein C rückwärts zeichnen, schwingt der Bogen 180 Grad in der negativen Richtung und das letzte Argument ist 180 (siehe Abb. 9.13).
Abbildung 9.13: Bögen auf Kreisen
Nachfolgend der Code für dieses Beispiel. Sie zeichnen damit eine C-Kontur und daneben ein gefülltes C wie in Abb. 9.14
Abbildung 9.14: Zwei kreisförmige Bögen
public void paint(Graphics g) { g.DRAWArc(20,20,60,60,90,180); g.fillArc(120,20,60,60,90,180); }
Mit Kreisen können Bögen gut dargestellt werden. Bögen aus Ellipsen sind etwas schwieriger. Wir gehen jetzt den gleichen Prozeß durch, um den in Abb. 9.15 dargestellten Bogen zu zeichnen
Abbildung 9.15: Elliptischer Bogen
Wie beim Bogen aus einem Kreis ist dieser Bogen ebenfalls ein Stück eines kompletten Ovals, in diesem Fall eines elliptischen Ovals. Durch Vervollständigung des Ovals, aus dem dieser Bogen besteht, können Sie die Argumente für Anfangspunkt, Breite und Höhe der Methode drawArc bzw. fillArc ermitteln (siehe Abb. 9.16).
Abbildung 9.16: Bögen auf Ellipsen
Danach brauchen Sie nur noch den Anfangs- und den Schwingungswinkel zu ermitteln. Dieser Bogen beginnt nicht auf einer freundlichen Grenze wie 90 oder 180 Grad, deshalb müssen Sie ein wenig experimentieren. Der Bogen beginnt irgendwo in der Nähe von 25 Grad und schwingt 130 Grad im Uhrzeigersinn (siehe Abb. 9.17).
Abbildung 9.17: Anfangs- und Endpunkt
Damit sind alle Teile des Bogens ermittelt und Sie können den Code schreiben. Nachfolgend der Java-Code für diesen Bogen, einmal konturiert und einmal gefüllt (am gefüllten Beispiel können Sie erkennen, daß gefüllte Bögen wie Kreisabschnitte gezeichnet werden):
public void paint(Graphics g) { g.drawArc(10,20,150,50,25,-130); g.fillArc(10,80,150,50,25,-130); }
Die zwei elliptischen Bögen sind in Abb. 9.18 dargestellt.
Abbildung 9.18: Zwei elliptische Bögen
Zusammenfassend hier noch einmal die Schritte zum Erstellen von Bögen in Java:
In diesem Abschnitt wird ein Beispiel eines Applets erklärt, das viele der integrierten Grafikobjekte nutzt, um eine grundlegende Form zu zeichnen. In diesem Beispiel handelt es sich um eine Tischlampe mit einem gepunkteten Schirm (mit ein bißchen Vorstellungskraft sieht das wie ein kubistischer Pilz aus). Listing 9.1 enthält den vollständigen Code für die Lampe. Abb. 9.19 zeigt das daraus resultierende Applet.
Abbildung 9.19: Das Lamp-Applet
1: import java.awt.*; 2: 3: public class Lamp extends java.applet.Applet { 4: 5: public void paint(Graphics g) { 6: // Stellfläche für Lampe 7: g.fillRect(0,250,290,290); 8: 9: // Lampenfuß 10: g.drawLine(125,250,125,160); 11: g.drawLine(175,250,175,160); 12: 13: // Lampenschirm, obere und untere Kante 14: g.drawArc(85,157,130,50,-65,312); 15: g.drawArc(85,87,130,50,62,58); 16: 17: // Lampenschirm, Seiten 18: g.drawLine(85,177,119,89); 19: g.drawLine(215,177,181,89); 20: 21: // Punkte auf dem Schirm 22: g.fillArc(78,120,40,40,63,-174); 23: g.fillOval(120,96,40,40); 24: g.fillArc(173,100,40,40,110,180); 25: } 26: }
Nachdem Sie nun ein paar Dinge am Bildschirm gezeichnet haben, möchten Sie sie sicherlich verschieben oder kopieren oder gar das ganze Applet löschen. Die Graphics-Klasse bietet Methoden für diese Operationen.
Mit der Methode copyArea können Sie einen rechteckigen Bereich am Bildschirm in einen anderen Bildschirmbereich kopieren. copyArea erhält sechs Argumente: x und y der oberen Ecke des zu kopierenden Rechtecks, Breite und Höhe des Rechtecks und Entfernung in x- und y-Richtung, in die zu kopieren ist. Die folgende Zeile kopiert beispielsweise einen viereckigen Bereich von 100 Pixeln um 100 Pixel direkt nach rechts auf der gleichen Seite:
g.copyArea(0,0,100,100,100,0);
Zum Löschen eines rechteckigen Bereichs benutzen Sie die clearRect-Methode. clearRect hat die gleichen vier Argumente wie drawRect und fillRect und füllt das betreffende Rechteck mit der aktuellen Hintergrundfarbe des Applets (Sie lernen noch heute, wie die aktuelle Hintergrundfarbe eingestellt wird).
Um das ganze Applet zu löschen, können Sie die size()-Methode anwenden, die ein Dimension-Objekt ausgibt, das die Breite und Höhe des Applets darstellt. Dann können Sie die aktuellen Werte für die Breite und Höhe holen, indem Sie die Instanzvariablen für Breite und Höhe benutzen:
g.clearRect(0,0,this.size().width,this.size().height());
Die Graphics-Klasse ermöglicht Ihnen auch die Ausgabe von Text am Bildschirm in Verbindung mit der Font-Klasse und teilweise auch mit der Klasse Font metrics. Die Font-Klasse stellt einen bestimmten Font - Name, Stil und Punktgröße - dar, während Font metrics Informationen über einen Font enthält (z. B. die tatsächliche Höhe oder Breite eines bestimmten Zeichens), so daß Sie Text in Ihrem Applet sehr präzise auslegen können.
Beachten Sie, daß in diesem Zusammenhang von statischem Text die Rede ist, der einmal am Bildschirm gezeichnet und dann unverändert angezeigt wird. Sie lernen später in dieser Woche, wie Text über die Tastatur eingegeben wird.
Um Text am Bildschirm ausgeben zu können, müssen Sie zuerst eine Instanz der Font-Klasse erstellen. Fontobjekte stellen einen einzelnen Font dar, d. h. Name, Stil (Fett, Kursiv) und Punktgröße. Fontnamen sind Zeichenketten, die die Schriftfamilie bezeichnen, z. B. TimesRoman, Courier oder Helvetica. Fontstile sind Konstanten, die durch die Font-Klasse definiert sind. Sie können sie anhand von Klassenvariablen holen, z. B. Font.PLAIN, Font.BOLD oder Font.ITALIC. Die Punktgröße ist die Größe der betreffenden Schriftart entsprechend der im Font enthaltenen Definition. Die Punktgröße kann, muß aber nicht die Höhe der Zeichen sein.
Um ein einzelnes Fontobjekt zu erstellen, benutzen Sie die folgenden drei Argumente für den neuen Constructor der Font-Klasse:
Font f = new Font("TimesRoman", Font.BOLD, 24);
Dieses Beispiel erstellt ein Fontobjekt für die Schriftart TimesRoman Fett in 24 Punkt. Beachten Sie, daß Sie diese wie die meisten Java-Klassen zuerst importieren müssen.
Fontstile sind ganzzahlige Konstanten, die kombiniert hinzugefügt werden können, z. B. Font.BOLD + Font.ITALIC, um den Text Fett und Kursiv auszugeben.
Welche Fonts Ihnen in einem Applet zur Verfügung stehen, hängt von dem System ab, auf dem das Applet läuft. Derzeit gibt es zwar einen Mechanismus in Java, um eine Fontliste abzurufen (siehe getFontList-Methode in der Klasse java.awt.Toolkit), jedoch scheint dies in der Beta-Version von JDK derzeit nicht zu funktionieren. Sobald diese Merkmale zur Verfügung stehen, können Sie eine Liste der auf dem System verfügbaren Fonts anzeigen und Schriftarten anhand dieser Liste auswählen. Vorläufig müssen Sie sicherstellen, daß Ihre Applets mit allen Systemen kompatibel sind. Deshalb sollten Sie die Fonts, die Sie in Ihren Applets verwenden, auf TimesRoman, Courier und Helvetica beschränken. Kann Java einen ausgewählten Font nicht finden, wird er durch die Standardschrift, normalerweise Courier, ersetzt.
Mit einem Fontobjekt können Sie mit den Methoden drawChars und drawString Text am Bildschirm ausgeben. Zuerst müssen Sie aber den aktuellen Font für Ihr Fontobjekt mit der Methode setFont setzen.
Der aktuelle Font ist Teil des Grafikzustands, der von dem Graphics-Objekt, in dem Sie zeichnen, verfolgt wird. Jedesmal, wenn Sie ein Zeichen oder eine Zeichenkette am Bildschirm ausgeben, wird dieser Text im aktuellen Font gezeichnet. Um die Schriftart des Textes zu ändern, ändern Sie zuerst den aktuellen Font. Im folgenden sehen Sie eine paint()-Methode, die einen neuen Font bestimmt, diesen als aktuellen Font definiert und die Zeichenkette »This is a big font.« ab Punkt 10,100 ausgibt.
public void paint(Graphics g) { Font f= new Font("TimesRoman", Font.PLAIN,72); g.setFont(f); g.drawString("This is a big font.",10,100); }
Das dürfte Ihnen bekannt vorkommen. Auf diese Weise wurden alle Beispiele des Hello-Applets bisher in diesem Buch produziert.
Die zwei letzten Argumente für drawString bestimmen den Punkt, an dem die Zeichenkette beginnt. Der x-Wert ist der Anfang des linken Textrandes. y ist die Grundlinie für die gesamte Zeichenkette.
Die drawChars-Methode ist ähnlich, hat jedoch als Argument keine Zeichenkette, sondern eine Reihe von Zeichen. drawChars hat fünf Argumente: Die Reihe der Zeichen, eine Ganzzahl n, die das erste Zeichen der Reihe darstellt, eine weitere Ganzzahl für das letzte Zeichen der Reihe (alle Zeichen zwischen dem ersten und letzten werden gezeichnet) sowie x und y für den Anfangspunkt. drawString ist in den meisten Fällen nützlicher als drawChars.
Listing 9.2 zeigt ein Applet, das mehrere Textzeilen in unterschiedlichen Fonts zeichnet. Das Ergebnis ist in Abb. 9.20 dargestellt.
Listing 9.2: Das ManyFonts-Applet
1: import java.awt.Font; 2: import java.awt.Graphics; 3: 4: public class ManyFonts extends java.applet.Applet { 5: 6: public void paint(Graphics g) { 7: Font f = new Font("TimesRoman", Font.PLAIN, 18); 8: Font fb = new Font("TimesRoman", Font.BOLD, 18); 9: Font fi = new Font("TimesRoman", Font.ITALIC, 18); 10: Font fbi = new Font("TimesRoman", Font.BOLD + Font.ITALIC, 18), 11: 12: g.setFont(f); 13: g.drawString("This is a plain font", 10, 25); 14: g.setFont(fb); 15: g.drawString("This is a bold font", 10, 50); 16: g.setFont(fi); 17: g.drawString("This is an italic font", 10, 75); 18: g.setFont(fbi); 19: g.drawString("This is a bold italic font", 10, 100); 20: } 21: 22: }
Abbildung 9.20: Ausgabe des Applets "ManyFonts"
Hier und da müssen Sie eventuell Entscheidungen in Ihrem Java-Programm auf der Grundlage der Qualität des aktuellen Fonts treffen, z. B. in bezug auf Punktgröße oder Gesamthöhe der Zeichen. Sie können einige grundlegende Informationen über Fonts und Fontobjekte anhand einfacher Methoden, die Sie auf Graphics und die Font-Objekte anwenden, herausfinden. Einige dieser Methoden sind in Tabelle 9.1 aufgeführt:
Methode |
in Objekt |
Aktion |
getFont() |
Graphics |
Gibt das zuvor durch setFont() gesetzte aktuelle Fontobjekt aus. |
getName() | Font | Gibt den Namen des Fonts als Zeichenkette aus. |
getSize() | Font | Gibt die Größe des aktuellen Fonts (als Ganzzahl) aus. |
getStyle() | Font | Gibt den Stil des aktuellen Fonts aus (Stile sind ganzzahlige Konstanten: 0 = Normal (PLAIN), 1 = Fett (BOLD), 2 = Kursiv (ITALIC), 3 = Fett Kursiv (BOLD ITALIC). |
isPlain() | Font | Gibt true oder false aus, wenn der Fontstil Normal ist. |
isBold() | Font | Gibt true oder false aus, wenn der Fontstil Fett ist. |
isItalic() |
Font |
Gibt true oder false aus, wenn der Fontstil Kursiv ist. |
Tabelle 9.1: Fontmethoden
Um weitere Informationen über den aktuellen Font (z. B. die Länge oder Höhe bestimmter Zeichen) zu erhalten, müssen Sie mit der Klasse FontMetrics arbeiten. Sie beschreibt spezifische Fonts in allen Einzelheiten. Um mit diesen Werten zu arbeiten, erstellen Sie ein FontMetrics-Objekt auf der Grundlage des aktuellen Fonts. Dafür verwenden Sie die Applet-Methode getFontMetrics:
Font f = new Font("TimesRoman", Font.bold, 36); FontMetrics fmetrics = getFontMetrics(f); g.setFont(f);
In Tabelle 9.2 sind einige interessante Elemente, die Sie mit FontMetrics herausfinden können, aufgeführt. Alle Methoden dieser Art werden für ein FontMetrics-Objekt aufgerufen
.
Methode |
Aktion |
stringWidth() | Gibt die volle Breite der Zeichenkette in Pixeln aus. |
charWidth() | Gibt die Breite eines bestimmten Zeichens aus. |
getAscent() | Gibt den Aufstrich, d. h. die Entfernung zwischen der Grundlinie und der oberen Grenze der Buchstaben, aus. |
getDescent() | Gibt den Abstrich, d. h. die Entfernung zwischen der Grundlinie und der unteren Grenze der Buchstaben, aus (z. B. bei p und q). /TR> |
getLeading() | Gibt Zeilenabstand, d. h. den Abstand zwischen dem Abstrich einer Zeile und dem Aufstrich der nächsten Zeile, aus. |
getHeight() | Gibt die Gesamthöhe der Schrift aus, d. h. die Summe von Aufstrich, Abstrich und Zeilenabstand. |
Tabelle 9.2: FontMetrics-Methoden
Als Beispiel der Informationen, die Sie mit FontMetrics verwenden können, zeigt Listing 9.3 den Java-Code eines Applets, das eine Zeichenkette automatisch horizontal und vertikal im Applet-Bereich zentriert. Die Zentrierposition ist unterschiedlich, je nach Schriftart und -größe. Durch Verwendung von FontMetrics-Informationen können Sie die tatsächliche Größe einer Zeichenkette ermitteln und sie an der richtigen Stelle ausgeben.
Die Methode applet.size() gibt in diesem Beispiel die Breite und Höhe des gesamten Applet-Bereichs als Dimension-Objekt aus. Sie können die individuelle Breite und Höhe dann mit den Instanzvariablen für Breite und Höhe holen.
Abb. 9.21 zeigt das Ergebnis (weniger interessant als das Kompilieren und Experimentieren mit verschiedenen Applet-Größen).
Listing 9.3: Zentrieren einer Zeichenkette
1: import java.awt.Font; 2: import java.awt.Graphics; 3: import java.awt.FontMetrics; 4: 5: public class Centered extends java.applet.Applet { 6: 7: public void paint(Graphics g) { 8: Font f = new Font("TimesRoman", Font.PLAIN, 36); 9: FontMetrics fm = getFontMetrics(f); 10: g.setFont(f); 11: 12: String s = "This is how the world ends."; 13: int xstart = (this.size().width - fm.stringWidth(s)) / 2; 14: int ystart = (this.size().height - fm.getHeight()) / 2; 15: 16: g.drawString(s, xstart, ystart); 17: } 18: }
Abbildung 9.21: Zentrierter Text
Das Zeichnen von schwarzen Linien und das Prüfen auf einem grauen Hintergrund ist schön und gut, jedoch ist alles bunt viel schöner. Java bietet Methoden und Eigenschaften zum allgemeinen Arbeiten mit Farben durch die Color-Klasse. Daneben gibt es Methoden zum Einrichten der aktuellen Vorder- und Hintergrundfarben, so daß Sie mit individuell erstellten Farbkombinationen zeichnen können.
Javas abstraktes Farbmodell nutzt 24-Bit-Farben, wobei eine Farbe als Kombination von Rot-, Grün- und Blauwerten dargestellt wird. Jede Komponente der Farbe kann eine Zahl zwischen 0 und 255 haben. 0,0,0 ist Schwarz, 255,255,255 ist Weiß. Daneben kann Java Millionen von Farbnuancen darstellen.
Javas abstraktes Farbmodell wird auf das Farbmodell des Systems abgebildet, auf dem Java läuft, was normalerweise nur 256 Farben oder weniger bietet. Ist eine angeforderte Farbe in einem Farbobjekt nicht zur Anzeige verfügbar, kann die daraus resultierende Farbe auf eine andere abgebildet werden, je nach dem, wie der Browser die Farbe implementiert und je nach Plattform, auf der man arbeitet. Mit anderen Worten: Java gibt zwar die Möglichkeit der Handhabung von Millionen von Farben, jedoch sind in Wirklichkeit eventuell nur einige wenige verfügbar.
Um ein Objekt in einer bestimmten Farbe zu zeichnen und darzustellen, müssen Sie eine Instanz der Color-Klasse erstellen. Die Color-Klasse definiert verschiedene Standardfarbobjekte, die in Klassenvariablen gespeichert sind und eine schnelle Möglichkeit bieten, ein Farbobjekt in einer gängigen Farbe zu holen. Mit Color.red erhalten Sie beispielsweise ein Color-Objekt, das Rot (RGB-Wert von 255, 0 und 0) darstellt. Color.white ergibt Weiß (RGB-Wert von 255, 255 und 255) usw. In Tabelle 9.3 sind die durch Variablen in der Color-Klasse definierten Standardfarben aufgeführt.
Farbname | RGB-Wert |
Color.white Color.black Color.lightGray Color.,gray Color.darkGray Color.red Color.green Color.blue Color.yellow Color.magenta Color.cyan Color.pink Color.orange |
255,255,255 0,0,0 192,192,192 128,128,128 64,64,64 255,0,0 0,255,0 0,0,255 255,255,0 255,0,255 0,255,255 255,175,175 255,200,0 |
Tabelle 9.3: Standardfarben
Keine Sorge, falls sich die gewünschte Farbe nicht unter den Standardfarbobjekten befindet. Sie können ein Farbobjekt durch jede beliebige Kombination aus Rot, Grün und Blau erstellen, sofern Sie die Werte der gewünschten Farbe kennen. Sie erstellen einfach ein neues Objekt:
Color c = new Color(140,140,140);
Mit diesem Java-Code wird ein Farbobjekt für Dunkelgrau erstellt. Alternativ können Sie ein Farbobjekt auch unter Verwendung von drei Gleitpunktzahlen von 0.0 bis 1.0 erstellen:
Color c = new Color(0.34,1.0,0.25)
Um ein Objekt oder einen Text mit einem Farbobjekt zu zeichnen, müssen Sie wie beim Einrichten des aktuellen Fonts ein Farbobjekt für die aktuelle Farbe erstellen. Verwenden Sie die setColor-Methode (für Graphics-Objekte):
g.setColor(Color.green);
Danach werden alle Zeichnungsoperationen in dieser Farbe abgesetzt.
Zusätzlich zum Einrichten der aktuellen Farbe für den Grafikinhalt können Sie für das Applet selbst eine Vorder- und Hintergrundfarbe setzen. Sie verwenden dafür die Methoden setBackground und setForeground. Beide Methoden sind in der Klasse java.awt.Component definiert. Von dieser Klasse erbt Applet und damit alle Ihre Klassen automatisch.
Die setBackground-Methode setzt die Hintergrundfarbe für das Applet, normalerweise Dunkelgrau. Sie hat ein einziges Argument - ein Farbobjekt:
setBackground(Color.white);
Die Methode setForeground hat ebenfalls nur eine Farbe als Argument und wirkt sich auf alles aus, das im Applet gezeichnet wird, ungeachtet der Farbe, in der es gezeichnet wurde. Sie können setForeground verwenden, um die Farbe aller Elemente im Applet in einem Zug zu ändern, so daß Sie nicht jedes einzelne Element neu zeichnen müssen:
setForeground(Color.black);
Abgesehen von den Methoden setColor, setForeground und setBackground gibt es noch entsprechende get-Methoden, mit denen Sie die aktuelle Grafikfarbe sowie Hintergrund und Vordergrund abrufen können. Diese Methoden sind getColor (in Graphics-Objekten definiert), getForeground (in Applet definiert) und getBackground (ebenfalls in Applet definiert). Sie können diese Methoden anwenden, um Farben auf der Grundlage von bereits im Applet vorhandenen Farben zu wählen:
setForeground(g.getColor());
Listing 9.4 enthält den Code für ein Applet, das den Applet-Bereich mit viereckigen Kästchen ausfüllt, die jeweils in einer zufällig gewählten Farbe abgesetzt sind. Der Code ist so geschrieben, daß er sich für jede Applet-Größe eignet und den Bereich automatisch mit der richtigen Anzahl von Kästchen füllt.
Listing 9.4: Kästchen mit zufällig gewählten Farben
1: import java.awt.Graphics; 2: import java.awt.Color; 3: 4: public class ColorBoxes extends java.applet.Applet { 5: 6: public void paint(Graphics g) { 7: int rval, gval, bval; 8: 9: for (int j = 30; j < (this.size().height -25); j += 30) 10: for (int i = 5; i < (this.size().width -25); i += 30) { 11: rval = (int)Math.floor(Math.random() * 256); 12: gval = (int)Math.floor(Math.random() * 256); 13: bval = (int)Math.floor(Math.random() * 256); 14: 15: g.setColor(new Color(rval,gval,bval)); 16: g.fillRect(i,j,25,25); 17: g.setColor(Color.black); 18: g.drawRect(i-1,j-1,25,25); 19: } 20: } 21: }
Da diese paint-Methode jedesmal, wenn das Applet ausgeführt wird, neue Farben erzeugt, können Sie die Farben regenerieren, indem Sie das Fenster verschieben oder das Applet-Fenster durch ein anderes verdecken. Abb. 9.22 zeigt das endgültige Applet (allerdings hier in Schwarzweiß und Grau, so daß Sie die vielfarbigen Kästchen leider nicht sehen können).
Abbildung 9.22: Applet mit zufällig gewählten Farbkästchen
Sie stellen etwas am Bildschirm dar, indem Sie im Inneren Ihres Applets zeichnen. Dafür können Sie Formen, Grafiken, Text oder Bilder verwenden. Heute haben Sie die Grundlagen des Zeichnens in Java gelernt. Sie haben gelernt, wie die integrierten Grafiken verwendet werden, um einfache Formen zu zeichnen, wie Fonts und Fontinformationen verwendet werden, um Text auszugeben, und wie mit Color-Objekten die Farbe der dargestellten Formen geändert werden kann. Damit haben Sie die Grundlage zum Zeichnen in einem Applet erlernt, um Animationen zu erstellen (für die im Grunde eine Zeichnung einfach wiederholt am Bildschirm ausgegeben wird) und mit Bildern zu arbeiten. Diese Techniken lernen Sie morgen.
F: In allen hier dargestellten Beispielen und in allen Tests, die ich durchgeführt habe, werden mit Grafikelementen wie drawLine und drawRect Linien produziert, die ein Pixel breit sind. Wie kann ich dickere Linien zeichnen?
A: In der derzeitigen Version der Graphics-Klasse von Java ist das nicht möglich. Es gibt keine Methoden zum Ändern der Standardbreite. Wenn Sie unbedingt dickere Linien zeichnen wollen, müssen Sie mehrere Linien in je einem Pixel Abstand zeichnen, um diese Wirkung zu erzielen.
F: Ich habe ein Applet mit Helvetica geschrieben. Auf meinem System läuft das wunderbar, jedoch nicht auf dem meines Freundes. Auf seinem System wird alles in Courier ausgegeben. Woran liegt das?
A: Auf dem System Ihres Freundes ist Helvetica höchstwahrscheinlich nicht installiert. Wenn Java einen Font nicht findet, ersetzt es ihn durch eine Standardschrift, meist Courier. Die beste Lösung hierfür ist die Durchsicht der Fontliste. Bei Drucklegung funktionierte die Abfrage der Fontliste allerdings noch nicht, deshalb ist es ratsam, in Ihren Applets nur Times Roman oder Courier zu verwenden.
F: Ich habe das Applet, das Kästchen in zufällig gewählten Farben zeichnet, ausprobiert, erhalte aber jedesmal zahlreiche Kästchen in der gleichen Farbe. Werden die Farben wirklich zufällig ausgewählt, verstehe ich nicht, wie das sein kann.
A: Das hat zwei Gründe. Erstens ist der Zufallsgenerator, den ich für diesen Code (aus der Math-Klasse) benutzt habe, nicht besonders gut. Die Dokumentation für diese Methode übrigens auch nicht. Um ein besseres Zufallsergebnis zu erzielen, benutzen Sie die Random-Klasse aus dem Paket java.util.
Der zweite, eher wahrscheinliche Grund ist der, daß eventuell in Ihrem Browser oder auf Ihrem System nicht genügend Farben vorhanden sind, um alle Farben, die das Applet erzeugt, auszugeben. Falls Ihr System die breite Farbpalette, die in der Color-Klasse verfügbar ist, nicht produzieren kann oder der Browser zu viele Farben bereits für andere Dinge vergeben hat, erhalten Sie mehrere Kästchen mit der gleichen Farbe. Normalerweise benötigen Sie in einem Applet nicht so viele Farben, deshalb stellt sich dieses Problem in der Praxis nur selten.
Copyright ©1996 Markt&Technik