12.1 | Zeichnen von Objekten |
Jede Komponente in Java besitzt einen so genannten Grafikkontext. Auf diesen wird über das zugehörige Graphics-Objekt zugegriffen. Der Grafikkontext repräsentiert, vereinfacht ausgedrückt, die Zeichenfläche der jeweiligen Komponente. Über ihn ist es möglich, in eine bestimmte Komponente zu zeichnen.
Dies gilt beim AWT allerdings nur für Container und die Komponente Canvas. Das liegt daran, dass die anderen AWT-Komponenten durch Aufrufe der jeweiligen Systembibliotheken implementiert werden (z. B. ein Button, der unter dem X-Window-System durch Motif dargestellt wird). Die Implementierung dieser Komponenten sieht überhaupt keine Zeichenoperationen innerhalb der Anzeigefläche vor. Somit kann man nicht direkt in diese Komponenten zeichnen. Man kann nur deren Farbe (setForeground(), setBackground()) und Größe einstellen. Bei ihnen hat das Graphics-Objekt für den Programmierer keine weitere Bedeutung.
Eine Ausnahme stellen die Lightweight-Komponenten dar. Sie sind direkt von den Klassen Component bzw. Container abgeleitet, und ihre äußere Gestalt wird sogar durch die Zeichenoperationen des Grafikkontexts gezeichnet. Dasselbe gilt auch für die Komponenten des Swing-Toolkits, da auch sie auf dem Prinzip der Lightweight-Komponenten aufbauen.
Auf das Graphics-Objekt einer Komponente kann über die paint()-Methode zugegriffen werden.
Jedesmal, wenn eine Komponente neu gezeichnet werden soll, wird die Methode paint() automatisch vom Interpreter aufgerufen. Ein Aufruf von paint() erfolgt z. B. immer dann, wenn eine Komponente neu am Bildschirm dargestellt wird. Die paint()-Methode bekommt das Graphics-Objekt übergeben:public void paint(Graphics g)paint() enthält standardmäßig keinen Code. Will man bestimmte Objekte in eine Komponente zeichnen, muss man die paint()-Methode der jeweiligen Komponente überschreiben und mit entsprechendem Code füllen.
Das Graphics-Objekt besitzt verschiedene Methoden, mit deren Hilfe Objekte gezeichnet werden können. Ruft man innerhalb von paint() eine der Zeichenmethoden des übergebenen Graphics-Objekts auf, wird die gewünschte Figur in die betreffende Komponente gezeichnet.
Auf diese Weise wurden z. B. die Grafik-Buttons im Kapitel über Event-Handling implementiert.
Ein anderes kleines Beispiel:public class PaintDemo extends Applet { int x, y; // Textposition // Angezeigter Text final String text = "a little graphic demo in Java"; public void init(){ // Setzen des Fonts und der Hintergrundfarbe setFont(new Font("SansSerif", Font.PLAIN, 20)); setBackground(Color.white); } public void paint(Graphics g) { // Berechnen der Koordinaten // zur Zentrierung des Textes FontMetrics fm = getFontMetrics(g.getFont()); x = (int)(getSize().width - fm.stringWidth(text)) / 2; y = (int)(getSize().height - fm.getHeight()) / 2 + fm.getAscent(); g.drawString(text, x, y); // Anzeigen des Textes } }Obiges Beispiel zeichnet den Text »a little graphic demo in Java« horizontal und vertikal zentriert in das Applet.Zuerst wird der gewünschte Font und die Hintergrundfarbe eingestellt (Fonts werden im Abschnitt 12.5 behandelt). Genau wie einer Komponente kann man mit der Methode setFont() einem Grafikkontext einen Font zuweisen.
Der wichtigste Bestandteil des Beispiels ist die Zentrierung des Texts, die im folgenden besprochen wird. Der Text wird mit drawString()g.drawString(text, x, y);auf dem Bildschirm ausgegeben. x und y bilden die linke untere Position des Texts. Also berechnet sich x aus der Hälfte der Differenz von Applet- und Textbreite:x = (int)(getSize().width - fm.stringWidth(text)) / 2;Die Breite des Applets erhält man durch getSize(). Diese Methode ist Bestandteil der Klasse Component und liefert als Resultat ein Objekt der Klasse Dimension. Diese Klasse besitzt die Datenelemente width und height, die die Breite bzw. Höhe der Komponente enthalten.
Um die Breite des Texts herauszufinden, bedarf es eines Exemplars der Klasse FontMetrics. FontMetrics besitzt Methoden, welche die Ausmaße eines bestimmten Schriftsatzes liefern. Ein FontMetrics-Objekt des aktuellen Schriftsatzes erhält man mit:FontMetrics fm = getFontMetrics(g.getFont());Die getFont()-Methode des Grafikkontexts liefert den gerade eingestellten Font zurück. Die Eigenschaften von Font und FontMetrics werden an dieser Stelle nur kurz beschrieben. Ihnen ist der Abschnitt 12.5 gewidmet.
Über ein FontMetrics-Objekt kann man die Breite einer Zeichenfolge mit der Methode stringWidth() in Bezug auf den zugehörigen Font ermitteln.
Der y-Wert berechnet sich folgendermaßen:y = (int)(getSize().height - fm.getHeight(text)) / 2 + fm.getAscent(text);Zuerst wird die Differenz von Applet- und maximaler Schrifthöhe durch zwei geteilt. Zu diesem Wert wird fm.getAscent(text) addiert. Letzterer Ausdruck liefert den Abstand von der Grundlinie bis zur Obergrenze der Zeichen des Schriftsatzes. gm.getAscent(text) muss zum Schluss addiert werden, weil die y-Position der Grundlinie ermittelt werden muss. Damit ist die Schrift zentriert.
Wenn das Applet im Appletviewer betrachtet wird, kann seine Größe beliebig variiert werden. Der ausgegebene Text wird immer zentriert dargestellt sein, da das Applet neu gezeichnet werden muss, wenn sich seine Größe verändert. Durch diese Größenveränderung wird letztendlich die Methode paint() aufgerufen. Da die Position des Texts relativ zur Größe des Applets angegeben wurde, ändern sich bei einer Größenveränderung des Appletviewers auch die Koordinaten des Texts.
Graphics besitzt außer drawString() viele weitere Methoden, mit denen auf einfache Art und Weise grafische Objekte gezeichnet werden können.
Hier ein kleiner Auszug:Das Zeichenobjekt wird immer in der aktuellen Zeichenfarbe dargestellt. Farben werden in Java durch die Klasse Color repräsentiert. Das Festlegen der Zeichenfarbe wird mit der Methode setColor(Color) vorgenommen. Analog dazu besitzt das Graphics-Objekt eine Methode getColor(), mit der die aktuelle Zeichenfarbe abgefragt werden kann. Farben und Farbmodelle werden im Abschnitt 12.6 behandelt.
- drawString(String text, int x, int y)
Zeichnet einen String im aktuellen Font. Dessen Grundlinie befindet sich auf der mit y übergebenen y-Position und wird ab der x-Position x von links nach rechts gezeichnet.- drawRect(int x, int y, int width, int height)
Zeichnet ein Rechteck in den übergebenen Ausmaßen, wobei x und y die Position der linken oberen Ecke die des Rechtecks angeben.- drawOval(int x, int y, int width, int height)
Zeichnet eine Ellipse innerhalb des Rechtecks, das durch die übergebenen Parameter spezifiziert wird. Für die Angabe des Rechtecks gilt gleiches, was für drawRect() gesagt wurde.- drawLine(int x, int y, int x1, int y1)
Zeichnet eine Linie von x, y nach x1, y1.- drawArc(int x, int y, int width, int height, int start, int end)
Zeichnet einen Kreisbogen innerhalb des durch die ersten vier Parameter festgelegten Rechtecks. start legt den Startwinkel und end den Endwinkel fest. Der Winkel wird in Grad angegeben, ausgehend von der Drei-Uhr-Position im mathematisch positiven Sinn.
Die einzelnen Zeichenmethoden gibt es in unterschiedlichen Varianten, meist auch in einer Form, bei der das entsprechende Zeichenobjekt in der aktuellen Zeichenfarbe ausgefüllt wird. Dann steht fill statt draw im Methodennamen. Zum Zeichnen eines ausgefüllten Rechtecks wird z. B. fillRect() verwendet. Die einzelnen Methoden können der elektronischen Referenz entnommen werden.
Eine weitere erwähnenswerte Methode der Klasse Graphics ist translate(int x, int y). Mit ihr ist es möglich, das Koordinatensystem relativ zum Nullpunkt des Grafikkontexts zu verschieben:public void paint(Graphics g) { g.translate(50, 50); g.drawString("This is point 50, 50", 0, 0); }In dieser paint()-Methode wird ein Text an der Position 0, 0 ausgegeben. Dadurch, dass zuvor translate() mit den Parametern 50,50 aufgerufen wurde, wird der Nullpunkt des Koordinatensystems an diese Position verschoben.
Im Kapitel über Scroll-Events wurde diese Methode verwendet, um die Karte bei einer Verschiebung an der neuen Position anzuzeigen.
Das Graphics-Objekt enthält Informationen über:Alle diese Eigenschaften können über Methoden des Graphics-Objekts eingestellt werden. Die Namen der entsprechenden Methoden sind in obiger Auflistung in Klammern genannt. Es ist allerdings zu beachten, dass die Einstellungen, die innerhalb einer paint()-Methode am Graphics-Objekt gemacht werden, nur für einen Zeichenvorgang gelten. Das Graphics-Objekt, das beim nächsten Aufruf von paint() übergeben wird, befindet sich wieder in seinem ursprünglichen Zustand, d. h., alle beim letzten paint()-Aufruf gemachten Einstellungen sind verloren.
- Zeichenfarbe (setColor(Color)).
- Verschiebung zum Ursprung des Grafikkontexts
(translate(int, int))- Clipping-Region (setClip(int, int, int, int))
- Font (setFont(Font))
- Zeichenmodus (setPaintMode(), setXORMode(Color))
Die Standardeinstellungen für die Zeichenfarbe und den Font, die ein Graphics-Objekt besitzt, wenn es an paint() übergeben wurde, hängt von den Einstellungen der Komponente ab, zu dem das Graphics-Objekt gehört:Eine Änderung des Fonts bzw. der Farbe des Graphics-Objekts hat keinen Einfluss auf Font oder Farbe der Komponente. Eine Änderung von Font oder Vordergrundfarbe der Komponente bewirkt allerdings, dass beim nächsten Aufruf von paint() ein Graphics-Objekt übergeben wird, das als Voreinstellung den Font und als Zeichenfarbe die Vordergrundfarbe der Komponente besitzt.
- Die Zeichenfarbe des Graphics-Objekts wird auf die Vordergrundfarbe der Komponente gesetzt. (Kann über setForeground(Color) eingestellt werden.)
- Als Font der Graphics-Objekts wird der Font der Komponente eingestellt. (Wird mit setFont(Font) gesetzt.)