Die Java 2D API hat sehr ausgeprägte Fähigkeiten im Bereich der Textdarstellung. Von den vielen Möglichen Vorgehensweisen möchte ich mich hier auf zwei beschränken:
Graphics2D.drawString()
: restriktiv, aber unkompliziertjava.text.AttributedCharacterIterator
: aufwendig, aber vielfältiger
Um Text darstellen zu können, braucht man zunächst eine Schriftart. Schriftarten werden durch
die die Klasse java.awt.Font
repräsentiert. Die Font
-Klasse stellt u.a. folgenden
Konstruktor zur Verfügung:
Konstruktor | Beschreibung |
---|---|
Font(String name,int style,int size) |
Erstellt eine neue Schriftart mit der Schriftart name .
Unklar ist, was bei Mehrdeutigkeiten bezüglich des Namens der Schriftart
passiert.style ist ein Bitmaske, die durch Kombination der Bitmasken
BOLD, ITALIC, PLAIN entsteht. Die Kombination erfolgt
mit Hilfe des |-Operators.size gibt die Größe der Schriftart in Punkt an.
|
Die Methode
liefert ein Feld mit allen auf der jeweiligen Plattform verfügbaren Schriftarten.
Bei der Konstruktion von Schriftarten wird zwischen folgenden Arten von Bezeichnern für Schriftarten unterschieden:
serif
ergibt auf einem
Windows-System z.B. die Schriftart "Times New Roman". Die Abbildung eines logischen Namens auf eine Schriftart
übernimmt die Java Virtual Machine.Codebeispiel für das instantiieren einer Schriftart:
...
Font myFont=new Font( "Times New Roman",Font.BOLD|Font.ITALIC,18 );
...
Wann man mit Schriftarten arbeitet und Text in mehreren Zeilen darstellen möchte, ist es sinnvoll, die Abmessungen des auszugebenden Strings in der jeweiligen Schriftart zu kennen, um z.B. die Zeilenhöhe ermitteln zu können. Die allgemein gebräuchlichen Bezeichnungen möchte ich hier kurz anhand eines Schaubildes vorstellen:
Diese Abmessungen können für einen beliebigen String vom Font-Objekt ermittelt werden. Hierzu verwendet man die überladenegetLineMetrics
-Methode aus der Font
-Klasse. Sie
liefert ein java.awt.LineMetrics
-Objekt, dessen get...-Methoden
die dargestellten Abmessungen des übergebenen Strings zurückgeben.
Das folgende Beispielprogramm erzeugt zunächst ein font
-Objekt und gibt dann die Werte
für leading, descent und ascent für einen bestimmten String aus
(Zugriff auf die Quelle):
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
public class MyFontMetrics
{
public static void main( String[] kommandozeilenargumente )
{
//Font erzeugen
Font myFont=new Font("Arial", Font.ITALIC|Font.PLAIN, 26);
String s="Wieso ist das Kapitel über Schriftarten nur so interessant?";
// hole die Line Metrics für s
LineMetrics lm = myFont.getLineMetrics(
s,
new FontRenderContext(
new AffineTransform(),
true, //antialiased
true //use fractional metrics?
)
);
// Abmessungen für den String ausgeben:
System.out.println("String: "+s);
System.out.println("Schriftart: "+myFont.getFontName());
System.out.println("Schriftgröße: "+myFont.getSize());
System.out.println("-------------");
System.out.println("Ascent: "+lm.getAscent());
System.out.println("+Descent: "+lm.getDescent());
System.out.println("+Leading: "+lm.getLeading());
System.out.println("=Height: "+lm.getHeight());
}
}
Die Textausgabe mittels der überladenen Methode Graphics2D.drawString()
ist die einfachste Variante.
Der Nachteil hierbei ist, daß zu einzelnen Segementen eines Strings keine Formatinformationen gespeichert werden können.
Des weiteren kann es bei der Animation von Text zu rundungsbedingten, unerwünschten Nebeneffekten der Animation kommen
(Text bewegt sich unregelmäßig), wenn im Graphics2D
-Objekt der Rendering-Hint KEY_FRACTIONALMETRICS
deaktiviert ist.
Für animierten Text ist drawString
deshalb ungeeignet.
Folgende drawString()
-Methoden
existieren in Graphics2D
für die Ausgabe von Strings:
Methode | Beschreibung |
---|---|
drawString( String s, int x, int y ) |
zeichnet den String s in der aktuellen Schriftart bei der Position (x,y)
(als linke untere Ecke des Rechtecks, daß den String einschließt) in die Zeichenfläche. |
drawString(String s, float x, float y) |
wie vorherige Methode, aber mit float -Koordinaten |
Folgende paint
-Routine zeichnet einen String mit der Schriftart "Arial" in ein Graphics2D-Objekt.
public void paint(Graphics g) {
//Upcast --> mehr Funktionen in Graphics2D
Graphics2D g2d=(Graphics2D)g;
//Font erzeugen
Font myFont=new Font("Arial", Font.ITALIC|Font.PLAIN, 26);
String s="Textausgabe mit drawString()";
g2d.setFont( myFont ); //Schriftart setzen
g2d.drawString(s,50,50); //String rendern
}
Das Ergebnis sieht so aus:
Mit drawString
ist es nicht möglich, einzelnen Teilen eines Strings auch Formatierungsanweisungen
hinzuzufügen.
Hierzu kann man z.B. auf das Interface java.text.AttributedCharacterIterator
zurückgreifen, welches
vorschreibt, welche Methoden eine Klasse für einen formatierten String zu implementieren hat. Ein
AttributedCharacterIterator
soll es ermöglichen, iterativ einen String mit verschiedenen Formatanweisungen zu durchlaufen und
für die einzelnen Segemete den jeweiligen Substring und das damit verbundene Format auszulesen. Als Formatierungsanweisungen
können z.B. Farben, Schriftarten- und -stile eingesetzt werden.
Das JDK 1.3 enthält eine Klasse, die ein AttributedCharacterIterator
-Objekt, das von der überladenen Methode
Graphics2D.drawString
akzeptiert wird, zurückgeben kann: java.text.AttributedString
.
Diese Klasse kapselt einen attributierten String.
Die Schritte vom Erstellen einer AttributedString
-Instanz bis zur Ausgabe des Strings in ein Graphics2D
-Objekt sind
die folgenden:
AttributedString
, z.B. mit folgendem Konstruktor:Konstruktor | Beschreibung |
---|---|
AttributedString(String text) |
erstellt einen neuen AttributedString für den String text .
|
addAttribute(...)
-Methoden aus AttributedString
:
Methode | Beschreibung |
---|---|
addAttribute(AttributedCharacterIterator.Attribute attribute, Object value) |
fügt dem gesamten String ein Attribut hinzu. Das Attribut stammt aus
der Klasse java.awt.font.Textattribute , die Ausprägung des Attributes
ist ein zu dem jew. Attribut passendes Objekt. Welche Klassen zu welchen Attributen passen,
entnimmt man der Beschreibung der Klasse TextAttribute , aus der Java API Spezifikation.
|
addAttribute(AttributedCharacterIterator.Attribute attribute,
Object value, int beginIndex, int endIndex) |
wie vorherige Methode, aber das Attribut wird nur auf den durch die beiden Indizes
definierten Teilstring angewandt. Das erste Zeichen des Strings hat den Index 0. |
Graphics2D.drawString(...)
unter anderem ein AttributedCharacterIterator
-Objekt entgegennehmen kann, ist es an dieser Stelle notwendig,
dieses unter Verwendung der Methode AttributedCharacterIterator AttributedString.getIterator()
zu ermitteln.
AttributedCharacterIterator
-Objekt wird an drawString()
übergeben und der String
wird in die Zeichenfläche gerendert.
paint
-Routine zeichnet einen formatierten String in ein Graphics2D-Objekt:
public void paint(Graphics g) {
//Upcast --> mehr Funktionen in Graphics2D
Graphics2D g2d=(Graphics2D)g;
// Antialiasing einschalten
g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON );
// benötigte Fonts erzeugen
Font f1 = new Font("Arial", Font.PLAIN, 48);
Font f2 = new Font("Times New Roman", Font.PLAIN, 48);
// String mit Default-Attributen erzeugen
AttributedString as = new AttributedString("Roses are red, violets are blue");
// gesamter Text in Schrift f1
as.addAttribute( TextAttribute.FONT, f1 );
// "red" in rot-weißem, zyklischen Farbverlauf
as.addAttribute( TextAttribute.FOREGROUND, new GradientPaint(
0,0,
Color.red,
0,10,
Color.white ,true ),
10,13);
// "red" in Times New Roman
as.addAttribute( TextAttribute.FONT, f2, 10, 13 );
// "blue" in schwarz-blauem Farbverlauf
as.addAttribute( TextAttribute.FOREGROUND, new GradientPaint(
0,0,
Color.blue,
10,0,
Color.black ,true ),
27,31);
// "blue" auch in Times New Roman
as.addAttribute( TextAttribute.FONT, f2, 27, 31 );
// "Roses" unterstrichen mit gestrichelter Linie
as.addAttribute( TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_DASHED, 0,5 );
// "Violets invertiert"
as.addAttribute( TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON, 15,22 );
// formatierten String ausgeben
g2d.drawString( as.getIterator(), 100,100 );
}
Das Ergebnis sieht so aus:
Da die Verabeitung von Text in der Java 2D API ein sehr umfangreiches Themengebiet ist, möchte ich hier
aus Gründen der Komplexität nicht auf weitere Möglichkeiten eingehen. Die Klasse java.awt.font.TextLayout
bietet weitere Möglichkeiten der Textdarstellung, z.B. Editierfunktionen, Cursor-Support und mehrzeiligen, formatierten
Text.