Advanced
Java
Services
|
pluggable look and feel |
AWT-Komponenten werden betriebssystemabhängig dargestellt. Ein AWT-Button schaut unter Motif aus
wie ein Motif-Button eben aussieht und analog für andere Betriebssysteme. Man kann die Vorder-
und Hintergrundfarbe verändern, eine andere Schrift wählen und die Größe verändern und das war es
im wesentlichen. AWT-Komponenten überlassen ihre Darstellung hauptsächlich dem darunterliegenden
Betriebssystem. Daher kann man den AWT-Komponenten kein eigenständiges LAF (look and feel) geben,
es sei denn, man strickt es sich selbst, indem man von Component ableitet. Aber diese Arbeit kann man
sich sparen, das ist ja schon passiert und heißt dann Swing...
Swingkomponenten delegieren ihre Darstellung nicht ans Betriebssystem, sondern zeichnen sich selbst.
Dazu gibt es zu jeder von JComponent abgeleiteten Klasse JXxx eine Klasse XxxUI, die für die
Darstellung der jeweiligen JComponente verantwortlich ist (zu JButton ein ButtonUI, zu JList ein ListUI
etc.). U.a. werden also etwa paint()-Aufrufe von JXxx an XxxUI weitergeleitet. Lediglich die
ToplevelContainer JFrame, JWindow, JDialog und JApplet, die sich nicht von JComponent ableiten delegieren
ihre Darstellung nach wie vor ans OS. Auf Grund dieses Verhaltens nennt man JComponent und alle davon
abgeleiteten Klassen lightweight-Komponenten.
Das typische Erscheinungsbild einer bestimmten graphischen Oberfläche korrespondiert jeweils mit einer
Klasse vom Typ LookAndFeel, genauer gesagt mit einer Klasse, die sich immer von der abstrakten Klasse
LookAndFeel ableitet. In der Praxis leitet sich die entsprechende LAFklasse meist von BasicLookAndFeel
ab, da diese Klasse Standardarbeiten erledigt, die eigentlich für alle LAFs notwendig sind. Die folgende
Graphik zeigt die vier gängigsten LookAndFeelklassen.
Die folgende Tabelle bringt eine Übersicht über einige wichtige Methoden der Klasse LookAndFeel
public abstract class LookAndFeel
Konstruktor | |
LookAndFeel() |
Methoden | |
Returntyp | Name der Methode |
UIDefaults | getDefaults() This method is called once by UIManager.setLookAndFeel to create the look and feel specific defaults table. |
abstract String | getID() Return a string that identifies this look and feel. |
abstract String | getName() Return a short string that identifies this look and feel, e.g. "CDE/Motif". |
boolean | getSupportsWindowDecorations() Returns true if the LookAndFeel returned RootPaneUI instances support providing Window decorations in a JRootPane. New in 1.4 |
void | initialize() UIManager.setLookAndFeel calls this method before the first call (and typically the only call) to getDefaults(). |
abstract boolean | isNativeLookAndFeel() If the underlying platform has a "native" look and feel, and this is an implementation of it, return true. |
abstract boolean | isSupportedLookAndFeel() Return true if the underlying platform supports and or permits this look and feel. Es geht nur um "permits"... |
void | uninitialize() UIManager.setLookAndFeel calls this method just before we're replaced by a new default look and feel. |
Die wichtigste Methode aus der Klasse LookAndFeel ist getDefaults(). Sie liefert ein Objekt vom Typ
UIDefaults. UIDefaults ist eine spezialisierte Hashtable, also eine key/value-Tabelle. In dieser Tabelle
ist für jede JComponente ihr zu diesem LookAndFeel gehörendes outfit gespeichert. Hier einige Beispiele
von key/value Einträgen in UIDefaults für MetalLookAndFeel.
key | value |
Button.background | javax.swing.plaf.ColorUIResource[r=204,g=204,b=204] |
Button.font | javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=bold,size=12] |
Button.textIconGap | 4 |
... | ... |
ButtonUI | javax.swing.plaf.metal.MetalButtonUI |
List.focusCellHighlightBorder | javax.swing.plaf.BorderUIResource$LineBorderUIResource |
List.selectionBackground | javax.swing.plaf.ColorUIResource[r=204,g=204,b=255] |
Button.textIconGap | 4 |
... | ... |
ListUI | javax.swing.plaf.metal.BasicListUI |
... | ... |
Hauptsächlich werden in diesen Tabelle Farben, Fonts und Borders hinterlegt. Die Tabellen sind recht
umfangreich, für die vier oben erwähnten LAFs ergeben sich jeweils ca. 550 key/value Paare. Eine komplette
Liste für die vier StandardLookAndFeels findet man unter
UIDefaultWerte. getDefaults() aus LookAndFeel liefert nicht nur
diese Tabelle, sondern erzeugt sie auch.
UIManager
Wie erfährt nun eine Applikation, welches LAF für sie zuständig ist? Dafür gibt es den UIManager.
Beim Start einer Applikation und bevor das GUI mit setVisible(true) sichtbar wird, wird dieser
automatisch aktiv. Standardmäßig erzeugt er ein Objekt vom Typ MetalLookAndFeel, ruft zu diesem
Objekt getDefaults und hält so einen Zeiger auf die zugehörige UIDefaultstabelle.
Alle von JComponent abgeleitete Komponenten holen sich die Information zu ihrer Darstellung mit Hilfe der
Klasse UIManager.
Die Klasse UIManager ist der Ausgangspunkt um sich Informationen über Look And Feels zu holen und
gegebenenfalls Look And Feels zu installieren oder zu setzen. Wie man aus der API ersehen kann, ist
UIManager eine Klasse, die nur statische Methoden besitzt. Sie ist also eine typische Hilfsklasse, von
der man keine Instanzen anlegt. Hier einige Methoden dieser Klasse.
Einige Methoden | |
Returntyp | Name der Methode |
static String | getCrossPlatformLookAndFeelClassName() Returns the name of the LookAndFeel class that implements the default cross platform look and feel -- the Java Look and Feel (JLF). |
static UIDefaults | getDefaults() Returns the default values for this look and feel. |
static UIManager.LookAndFeelInfo[] | getInstalledLookAndFeels() Returns an array of objects that provide some information about the LookAndFeel implementations that have been installed with this software development kit. |
static LookAndFeel | getLookAndFeel() Returns the current default look and feel or null. |
static UIDefaults | getLookAndFeelDefaults() Returns the default values for this look and feel. |
static String | getSystemLookAndFeelClassName() Returns the name of the LookAndFeel class that implements the native systems look and feel if there is one, otherwise the name of the default cross platform LookAndFeel class. |
static ComponentUI | getUI(JComponent target) Returns the L&F object that renders the target component. |
static void | installLookAndFeel(String name, String className) Creates a new look and feel and adds it to the current array. |
static void | installLookAndFeel(UIManager.LookAndFeelInfo info) Adds the specified look and feel to the current array and then calls setInstalledLookAndFeels(javax.swing.UIManager.LookAndFeelInfo[]). |
static void | setInstalledLookAndFeels(UIManager.LookAndFeelInfo[] infos) Replaces the current array of installed LookAndFeelInfos. |
static void | setLookAndFeel(LookAndFeel newLookAndFeel) Sets the current default look and feel using a LookAndFeel object. |
static void | setLookAndFeel(String className) Sets the current default look and feel using a class name. |
MetalLookAndFeel und MotifLookAndFeel werden mit jedem JDK ausgeliefert, MacLookAndFeel und
WindowsLookAndFeel aus rechtlichen Gründen nur auf den jeweiligen Betriebssystemen. Wer MacLookAndFeel
zu privaten Zwecken ausprobieren will, kann es sich mit dem folgenden Link herunterladen. Wer verschiedene
LAFs ausprobieren will, findet bei "javatoo" ein schöne Auswahl.
Der UIManager unterscheidet zwischen einem gesetzen LookAndFeel und installierten LookAndFeels. Zu dem
einen gesetzten LAF existiert die Tabelle der UIDefaults, die verwendet wird, um das Aussehen der
Komponenten zu bestimmen. Daneben gibt es eine (meist kleine) Liste von installierten LAFs. Über diese
Liste erfährt man, welche anderen LAFs der UIManager noch kennt. Aus dieser Liste kann man dann ein
anderes LAF auswählen und es setzen. In disem Fall holt sich der UIManager eine neue UIDefaultsTabelle
von dem neuen LookAndFeelObjekt. Die installierten LAFs werden in einem Array verwaltet. Die Elemente
dieses Arrays sind vom Typ der statischen nested class UIManager.LookAndFeelInfo. Wie man aus dem
Quellcode erkennt, kapselt die Klasse lediglich zwei Strings.
public static class LookAndFeelInfo
{
private String name;
private String className;
public LookAndFeelInfo(String name, String className)
{
this.name = name;
this.className = className;
}
public String getName()
{
return name;
}
public String getClassName()
{
return className;
}
//...
}
Ein zusätzliches LookAndFeel installieren
Ein zusätzliches LAF wird am einfachsten mit der Methode
installiert. Das folgende Beispiel installiert zwei neue LAFs.
UIManager.installLookAndFeel("mac","com.sun.java.swing.plaf.mac.MacLookAndFeel") ;
UIManager.installLookAndFeel("kunststoff", "com.incors.plaf.kunststoff.KunststoffLookAndFeel" );
Entscheidend ist der zweite String. Will man das LAF später auch setzen, so muß er den kompletten Packagenamen zur Klasse XxxLookAndFeel enthalten. Dieses package legt man als JavaArchiv (xxx.jar) in das Verzeichnis %JAVA_HOME%/jre/lib/ext. Sie auch das Kapitel über packages unter Grundlagen2.