Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Neues in Java 7
2 Threads und nebenläufige Programmierung
3 Datenstrukturen und Algorithmen
4 Raum und Zeit
5 Dateien, Verzeichnisse und Dateizugriffe
6 Datenströme
7 Die eXtensible Markup Language (XML)
8 Dateiformate
9 Grafische Oberflächen mit Swing
10 Grafikprogrammierung
11 Netzwerkprogrammierung
12 Verteilte Programmierung mit RMI
13 RESTful und SOAP Web-Services
14 JavaServer Pages und Servlets
15 Applets
16 Datenbankmanagement mit JDBC
17 Technologien für die Infrastruktur
18 Reflection und Annotationen
19 Dynamische Übersetzung und Skriptsprachen
20 Logging und Monitoring
21 Java Native Interface (JNI)
22 Sicherheitskonzepte
23 Dienstprogramme für die Java-Umgebung
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
Java 7 - Mehr als eine Insel von Christian Ullenboom
Das Handbuch zu den Java SE-Bibliotheken
Buch: Java 7 - Mehr als eine Insel

Java 7 - Mehr als eine Insel
Rheinwerk Computing
1433 S., 2012, geb.
49,90 Euro, ISBN 978-3-8362-1507-7
Pfeil 10 Grafikprogrammierung
Pfeil 10.1 Grundlegendes zum Zeichnen
Pfeil 10.1.1 Die paint()-Methode für das AWT-Frame
Pfeil 10.1.2 Zeichnen von Inhalten auf ein JFrame
Pfeil 10.1.3 Auffordern zum Neuzeichnen mit repaint()
Pfeil 10.1.4 Java 2D-API
Pfeil 10.2 Einfache Zeichenmethoden
Pfeil 10.2.1 Linien
Pfeil 10.2.2 Rechtecke
Pfeil 10.2.3 Ovale und Kreisbögen
Pfeil 10.2.4 Polygone und Polylines
Pfeil 10.3 Zeichenketten schreiben und Fonts
Pfeil 10.3.1 Zeichenfolgen schreiben
Pfeil 10.3.2 Die Font-Klasse
Pfeil 10.3.3 Einen neuen Font aus einem gegebenen Font ableiten
Pfeil 10.3.4 Zeichensätze des Systems ermitteln *
Pfeil 10.3.5 Neue TrueType-Fonts in Java nutzen
Pfeil 10.3.6 Font-Metadaten durch FontMetrics *
Pfeil 10.4 Geometrische Objekte
Pfeil 10.4.1 Die Schnittstelle Shape
Pfeil 10.4.2 Kreisförmiges
Pfeil 10.4.3 Kurviges *
Pfeil 10.4.4 Area und die konstruktive Flächengeometrie *
Pfeil 10.4.5 Pfade *
Pfeil 10.4.6 Punkt in einer Form, Schnitt von Linien, Abstand Punkt/Linie *
Pfeil 10.5 Das Innere und Äußere einer Form
Pfeil 10.5.1 Farben und die Paint-Schnittstelle
Pfeil 10.5.2 Farben mit der Klasse Color
Pfeil 10.5.3 Die Farben des Systems über SystemColor *
Pfeil 10.5.4 Composite und Xor *
Pfeil 10.5.5 Dicke und Art der Linien von Formen bestimmen über Stroke *
Pfeil 10.6 Bilder
Pfeil 10.6.1 Eine Übersicht über die Bilder-Bibliotheken
Pfeil 10.6.2 Bilder mit ImageIO lesen
Pfeil 10.6.3 Ein Bild zeichnen
Pfeil 10.6.4 Programm-Icon/Fenster-Icon setzen
Pfeil 10.6.5 Splash-Screen *
Pfeil 10.6.6 Bilder im Speicher erzeugen *
Pfeil 10.6.7 Pixel für Pixel auslesen und schreiben *
Pfeil 10.6.8 Bilder skalieren *
Pfeil 10.6.9 Schreiben mit ImageIO
Pfeil 10.6.10 Asynchrones Laden mit getImage() und dem MediaTracker *
Pfeil 10.7 Weitere Eigenschaften von Graphics *
Pfeil 10.7.1 Eine Kopie von Graphics erstellen
Pfeil 10.7.2 Koordinatensystem verschieben
Pfeil 10.7.3 Beschnitt (Clipping)
Pfeil 10.7.4 Zeichenhinweise durch RenderingHints
Pfeil 10.7.5 Transformationen mit einem AffineTransform-Objekt
Pfeil 10.8 Drucken *
Pfeil 10.8.1 Drucken der Inhalte
Pfeil 10.8.2 Bekannte Drucker
Pfeil 10.9 Benutzerinteraktionen automatisieren, Robot und Screenshots *
Pfeil 10.9.1 Der Roboter
Pfeil 10.9.2 Automatisch in die Tasten hauen
Pfeil 10.9.3 Automatisierte Mausoperationen
Pfeil 10.9.4 Methoden zur Zeitsteuerung
Pfeil 10.9.5 Bildschirmabzüge (Screenshots)
Pfeil 10.9.6 Funktionsweise und Beschränkungen
Pfeil 10.9.7 MouseInfo und PointerInfo
Pfeil 10.10 Zum Weiterlesen

Rheinwerk Computing - Zum Seitenanfang

10.3 Zeichenketten schreiben und FontsZur nächsten Überschrift

Java kann Zeichenketten in verschiedenen Zeichensätzen (engl. fonts) auf die Zeichenfläche bringen. Zum Zeichnen gibt es unterschiedliche Methoden, von denen in jeder Java-Version Varianten und Klassen hinzukamen. Nicht viel besser ist es mit den Font-Informationen; auch dafür gibt es verwirrend viele Möglichkeiten zur Repräsentation der Metadaten.


Rheinwerk Computing - Zum Seitenanfang

10.3.1 Zeichenfolgen schreibenZur nächsten ÜberschriftZur vorigen Überschrift

Die Methode drawString() bringt eine Unicode-Zeichenkette mit sogenannten Glyphen, das sind konkrete grafische Darstellungen eines Zeichens, auf den Bildschirm – die Darstellung von Zeichen übernimmt in Java der Font-Renderer.

Abbildung

Abbildung 10.5: Koordinatenangaben von drawString() und drawRect() im Vergleich

Die Parameter von drawString() beschreiben die zu schreibende Zeichenkette sowie die x- und y-Koordinaten. Die Koordinaten bestimmen die Position der Schriftlinie – auch Grundlinie genannt (engl. baseline) –, auf der die Buchstaben stehen.

abstract class java.awt.Graphics
  • abstract void drawString(String s, int x, int y)
    Schreibt einen String in der aktuellen Farbe und dem aktuellen Zeichensatz.
  • abstract void drawString(AttributedCharacterIterator iterator, int x, int y)
    Schreibt einen String, der durch den Attribut-Iterator gegeben ist.
  • abstract void drawChars(char[] data, int offset, int length, int x, int y)
  • abstract void drawBytes(byte[] data, int offset, int length, int x, int y)
    Schreibt die Zeichenkette und bezieht die Daten aus einem Char- bzw. Byte-Feld.
Hinweis

Die Klasse TextLayout bietet weitergehende Möglichkeiten, etwa Farbhervorhebung, Cursor-Funktionalität oder über TextHitInfo Tests, welches Zeichen sich an welcher Koordinate befindet, was bei Mausklicks nützlich ist. Ein draw() vom TextLayout bringt den Textbaustein auf den Schirm. Die Dokumentation listet etwas Quellcode zur Verdeutlichung auf.


Rheinwerk Computing - Zum Seitenanfang

10.3.2 Die Font-KlasseZur nächsten ÜberschriftZur vorigen Überschrift

Die Methode drawString() verwendet immer den aktuellen Zeichensatz. Um diesen zu ändern, benutzen wir auf dem aktuellen Graphics-Objekt die Methode setFont(). Der Übergabeparameter ist ein Font-Objekt, das wir von woanders erfragen oder vorher erzeugen müssen.

Abbildung

Abbildung 10.6: UML-Diagramm der Klasse Font

class java.awt.Font
implements Serializable
  • Font(String name, int style, int size)
    Erzeugt ein Font-Objekt mit einem gegebenen Namen, einem gegebenen Stil und einer gegebenen Größe.

Für den Stil deklariert die Font-Klasse drei symbolische Konstanten: Font.PLAIN sowie Font.ITALIC und Font.BOLD, sodass keine Ganzzahlen als Argumente zu übertragen sind. Die Stil-Attribute können mit dem binären Oder oder dem arithmetischen Plus verbunden werden; ein fetter und kursiver Zeichensatz erreicht Font.BOLD | Font.ITALIC (beziehungsweise Font.BOLD + Font.ITALIC). Die Größe ist in Punkt angegeben, wobei ein Punkt 1/72 Zoll (in etwa 0,376 mm) entspricht. Der Name des Zeichensatzes ist entweder physikalisch (zum Beispiel »Verdana« oder »Geneva«) oder logisch mit Font-Konstanten DIALOG, DIALOG_INPUT, SANS_SERIF, SERIF und MONOSPACED, die später auf die physikalischen Font-Namen übertragen werden.[79](Die Webseite http://java.sun.com/javase/7/docs/technotes/guides/intl/fontconfig.html beschreibt diese Umsetzung.)

Beispiel

Ein Font-Objekt erzeugen:

Font f = new Font( Font.SERIF, Font.PLAIN, 14 );

Häufig wird dieses Zeichensatz-Objekt sofort in setFont() genutzt, so wie:

setFont( new Font( "Verdana", Font.BOLD, 20 ) );

Hinweis

Die Dokumentation spricht zwar von »Punkt«, in Java sind aber Punkt und Pixel bisher identisch. Würde das Grafiksystem wirklich in Punkt arbeiten, müsste es die Bildschirmauflösung und den Monitor mit berücksichtigen.

Ist im Programm der aktuell verwendete Zeichensatz nötig, können wir getFont() von der Graphics-Klasse verwenden:

abstract class java.awt.Graphics
  • abstract Font getFont()
    Liefert den aktuellen Zeichensatz.
  • abstract Font setFont(Font f)
    Setzt den Zeichensatz für das Graphics-Objekt.

Rheinwerk Computing - Zum Seitenanfang

10.3.3 Einen neuen Font aus einem gegebenen Font ableitenZur nächsten ÜberschriftZur vorigen Überschrift

Steht ein Font zur Verfügung und soll ausgehend von diesem ein neues Font-Objekt mit einer kleinen Änderung, etwa in der Größe oder im Attribut (fett, kursiv), hergestellt werden, so lassen sich die deriveFont()-Methoden einsetzen.

Beispiel

Ausgehend von einem existierenden Font-Objekt f soll ein neuer Font mit dem gleichen Zeichensatz und Stil abgeleitet werden, der jedoch 20 Punkt groß ist:

Font font = f.deriveFont( 20f );

class java.awt.Font
implements Serializable
  • Font deriveFont(int style)
    Wie der Originalzeichensatz, nur mit einem neuen Stil.
  • Font deriveFont(float size)
    Wie der Originalzeichensatz, nur mit einer neuen Größe. Der Parameter ist vom Typ float, damit Verwechslungen mit deriveFont(int) – das liefert einen neuen Font in normal, fett und/oder kursiv – ausgeschlossen sind.
  • Font deriveFont(int style, float size)
    Wie der Originalzeichensatz, nur mit einer neuen Größe und einem neuen Stil.
  • Font deriveFont(AffineTransformation trans)
    Erzeugt ein neues Font-Objekt, das über ein Transformationsobjekt modifiziert ist. Liefert ein neues Zeichensatzobjekt in der Größe von einem Punkt und keinem besonderen Stil.

Rheinwerk Computing - Zum Seitenanfang

10.3.4 Zeichensätze des Systems ermitteln *Zur nächsten ÜberschriftZur vorigen Überschrift

Um herauszufinden, welche Zeichensätze auf einem System installiert sind, liefert getAvailableFontFamilyNames() auf einem GraphicsEnvironment ein Feld mit Font-Objekten. Ein Objekt vom Typ GraphicsEnvironment beschreibt die Zeichensätze des Systems und liefert GraphicsDevice-Objekte. Ein GraphicsDevice ist eine Malfläche, also das, worauf das System zeichnen kann. Das kann der Bildschirm sein, aber auch ein Drucker oder eine Hintergrundgrafik. Die statische Fabrikmethode getLocalGraphicsEnvironment() liefert ein solches GraphicsEnvironment-Objekt.

Beispiel

Im folgenden Codesegment gibt eine Schleife alle Zeichensatznamen aus:

for ( String fonts : GraphicsEnvironment.getLocalGraphicsEnvironment().
getAvailableFontFamilyNames() )
System.out.println( fonts );

Auf meinem System liefert die Schleife die folgenden Zeilen:

Arial
Arial Black
Arial Narrow
...
Wingdings
Wingdings 2
Wingdings 3

abstract class java.awt.GraphicsEnvironment
  • static GraphicsEnvironment getLocalGraphicsEnvironment()
    Liefert das aktuelle GraphicsEnvironment-Objekt.
  • abstract Font[] getAllFonts()
    Liefert ein Feld mit allen verfügbaren Font-Objekten in einer Größe von einem Punkt.
  • abstract String[] getAvailableFontFamilyNames()
    Liefert ein Feld mit allen verfügbaren Zeichensatzfamilien.
  • abstract String[] getAvailableFontFamilyNames(Locale l)
    Liefert ein Feld mit verfügbaren Zeichensatzfamilien, die zu einer Sprache l gehören.

Rheinwerk Computing - Zum Seitenanfang

10.3.5 Neue TrueType-Fonts in Java nutzenZur nächsten ÜberschriftZur vorigen Überschrift

Die auf allen Systemen vordefinierten Standardzeichensätze sind etwas dürftig, obwohl die Font-Klasse selbst jeden installierten Zeichensatz einlesen kann. Da ein Java-Programm aber nicht von der Existenz eines bestimmten Zeichensatzes ausgehen kann, ist es praktisch, einen Zeichensatz mit der Installation auszuliefern und dann diesen zu laden; das kann die Font-Klasse mit der statischen Methode createFont() sein. Aus einem Eingabestrom liest die Methode den TrueType-Zeichensatz und erstellt das entsprechende Font-Objekt.

Listing 10.5: com/tutego/insel/ui/graphics/TrueTypePanel.java, Ausschnitt

Font font = Font.createFont( Font.TRUETYPE_FONT,
getClass().getResourceAsStream( "/NASALIZA.TTF") );

Das erste Argument ist immer Font.TRUETYPE_FONT. Das zweite Argument bestimmt den Eingabestrom zur Binärdatei mit den Zeichensatzinformationen. Die Daten werden ausgelesen und zu einem Font-Objekt verarbeitet.

Waren die Beschreibungsinformationen in der Datei ungültig, so erzeugt die Font-Klasse eine FontFormatException("Unable to create font – bad font data"). Dateifehler fallen nicht darunter und werden extra über eine IOException angezeigt. Der Datenstrom wird anschließend nicht wieder geschlossen.

An dieser Stelle verwundert es vielleicht, dass die Arbeitsweise der statischen Methode createFont() der des Konstruktors ähnlich sein müsste, aber der Parameterliste die Attribute fehlen. Das liegt daran, dass die Methode automatisch einen Zeichensatz der Größe 1 im Stil Font.PLAIN erzeugt. Um einen größeren Zeichensatz zu erzeugen, müssen wir ein zweites Font-Objekt anlegen, was am einfachsten mit der Methode deriveFont() geschieht.

class java.awt.Font
implements Serializable
  • static Font createFont(int fontFormat, InputStream fontStream)
    throws FontFormatException, IOException
    Liefert ein neues Zeichensatzobjekt in der Größe von einem Punkt und mit keinem besonderen Stil.

Soll nicht direkt der Font verwendet werden, sondern soll der Zeichensatz unter seinem Namen in den Namensraum gelegt werden, sodass er später auch über den Font-Konstruktor gefunden werden kann, lässt er sich mit registerFont() anmelden. Das sieht etwa so aus:

GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont( font );

Rheinwerk Computing - Zum Seitenanfang

10.3.6 Font-Metadaten durch FontMetrics *Zur nächsten ÜberschriftZur vorigen Überschrift

Jedes Font-Objekt beinhaltet Informationen zur Schriftsatzfamilie, zum Schriftsatznamen sowie zu Größe und Stil. Was es nicht bietet, ist Zugriff auf Metadaten, etwa auf Abmessungen des Zeichensatzes. Um diese Daten aufzuspüren, ist ein FontMetrics-Objekt nötig. Es verwaltet metrische Informationen, die mit einer Schriftart verbunden sind. Dazu gehören Ober- und Unterlänge, Schrifthöhe und Zeilenabstand.

Da die Klasse FontMetrics keinen öffentlichen Konstruktor und keine statische Fabrikmethode besitzt, müssen wir ein FontMetrics-Objekt von einer anderen Stelle aus erfragen. Es bieten sich unter anderem an:

  • getFontMetrics() von Graphics
  • getFontMetrics(Font) von Graphics
  • getFontMetrics(Font) von Component
  • getFontMetrics(Font) von Toolkit (deprecated)

Ein FontMetrics-Objekt lässt sich merkwürdigerweise nicht direkt vom Font-Objekt erfragen. (Umgekehrt liefert aber getFont() aus FontMetrics das Font-Objekt, das diese Metriken beschreibt.)

In der paint()-Methode kann also mittels

FontMetrics fm = g.getFontMetrics();

auf die Metriken des aktuellen Zeichensatzes zugegriffen werden.

abstract class java.awt.Graphics
  • FontMetrics getFontMetrics()
    Liefert die Font-Metriken zum aktuellen Zeichensatz.
  • abstract FontMetrics getFontMetrics(Font f)
    Liefert die Font-Metriken für den Zeichensatz f.

Die Klasse FontMetrics bietet die folgenden Methoden an, wobei sich alle Angaben auf das jeweilige Zeichensatzobjekt beziehen. Beziehen sich die Rückgabeparameter auf die Zeichengröße, so erfolgt die Angabe immer in Pixeln.

abstract class java.awt.FontMetrics
implements Serializable
  • int charWidth(int ch)
  • int charWidth(char ch)
    Liefert die Breite zu einem Zeichen.
  • int charsWidth(char[] data, int off, int len)
  • int bytesWidth(byte[] data, int off, int len)
    Gibt die Breite aller Zeichen des Felds zurück. Beginnt bei off und liest len Zeichen.
  • int stringWidth(String str)
    Gibt die Breite der Zeichenkette zurück, wenn diese gezeichnet würde. Die Methode nutzt intern charsWidth().
  • int getAscent()
    Gibt den Abstand von der Grundlinie zur oberen Grenze (Oberlänge) zurück. Ist standardmäßig getSize() vom Font-Objekt.
  • int getDescent()
    Gibt den Abstand von der Grundlinie zur unteren Grenze (Unterlänge) zurück, standardmäßig 0.
  • int getLeading()
    Gibt den Durchschuss (engl. leading) zurück. Der Durchschuss ist der Standard-Abstand zwischen zwei Zeilen.
  • int getHeight()
    Gibt den Standard-Zeilenabstand (Abstand zwischen Grundlinie und Grundlinie) in Pixeln zurück. Er berechnet sich aus Durchschuss + Oberlänge + Unterlänge. In Quellcode ausgedrückt: getAscent() + getDescent() + getLeading().
  • int getMaxAdvance()
    Liefert die Breite des breitesten Zeichens bzw. –1, wenn unbekannt.
  • int getMaxAscent()
    Liefert das Maximum aller Oberlängen in Pixeln. Einige Zeichen können sich oberhalb der Oberlänge bewegen. Die Standard-Implementierung leitet einfach nur an getAscent() weiter.
  • int getMaxDescent()
    Liefert das Maximum aller Unterlängen in Pixeln. Leitet standardmäßig an getDescent() weiter.
  • int[] getWidths()
    Liefert in einem Ganzzahlfeld die Breiten – ermittelt durch charWidth() – der ersten 256 Zeichen zurück.
  • Font getFont()
    Liefert den aktuellen Zeichensatz.

Abbildung

Abbildung 10.7: Die wichtigsten Properties der Font-Metadaten

Hinweis

Die Ergebnisse von FontMetrics sind bescheiden und mitunter ungenau. Bessere Ergebnisse, etwa über die Maße eines zu zeichnenden Strings, und interessante Zusatzmethoden bieten FontRenderContext, TextLayout und LineMetrics:

Font font = ...;
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout( "Text", font, frc );
Rectangle2D bounds = layout.getBounds();

LineMetrics bietet Angaben, wie zum Beispiel die nötige Dicke einer Linie beim Unterstreichen und Durchstreichen:

Font font = ...;
FontRenderContext frc =;
LineMetrics lm = font.getLineMetrics( str, g.getFontRenderContext() );

Abbildung

Abbildung 10.8: Klassendiagramm von FontMetrics

Einen String unterstreichen

Wir wollen nun stringWidth() und die Metadaten nutzen, um einen unterstrichenen Text darzustellen. Dafür gibt es keine offensichtliche Standardmethode in der Java-API. Also schreiben wir uns eine eigene statische Methode drawUnderlinedString(), die die Koordinaten sowie den String übergeben bekommt und dann mit drawString() die Zeichenkette schreibt. Als Zweites zeichnet drawLine() eine Linie unter der Grundlinie des Textes mit einer Verschiebung und Dicke, die das von Graphics erfragte LineMetrics angibt, und mit der Länge, die das FontMetrics-Objekt für die Zeichenkette liefert:

Listing 10.6: com/tutego/insel/ui/graphics/DrawUnderlinedString.java, drawUnderlinedString()

public static void drawUnderlinedString( Graphics g, int x, int y, String s )
{
g.drawString( s, x, y );

FontMetrics fm = g.getFontMetrics();
LineMetrics lm = fm.getLineMetrics( s, g );

g.fillRect( x, y + (int) lm.getUnderlineOffset(),
fm.stringWidth(s), (int) lm.getUnderlineThickness() );
}

Natürlich achtet so eine kleine Methode nicht auf das Aussparen von Buchstaben, die unter der Grundlinie liegen, und so sind Buchstaben wie »y« oder »q« unten gnadenlos durchgestrichen.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück
  Zum Katalog
Neuauflage: Java SE 8 Standard-Bibliothek
Neuauflage: Java SE 8 Standard-Bibliothek
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Professionell entwickeln mit Java EE 7






 Professionell
 entwickeln mit
 Java EE 7


Zum Katalog: Java ist auch eine Insel






 Java ist auch
 eine Insel


Zum Katalog: Einstieg in Eclipse






 Einstieg in Eclipse


Zum Katalog: Einstieg in Java






 Einstieg in Java


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2012
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de