Swing-Komponenten neu erstellen oder verändern und JLayer
0 Kommentar(e). Veröffentlicht von Christian Ullenboom am Mittwoch, November 04, 2009.
Zum Aufbau neuer Swing-Komponenten kommen eine Reihe von Möglichkeiten in Frage. Wenn passend, lässt sich eine existierende Swing-Komponente als Basisklasse nehmen und um nötige Eigenschaften erweitern, sofern die Basisklassen diese Möglichkeit im Grunde schon bieten. Soll etwa ein Texteingabefeld nur IP-Adressen zulassen, so ist dafür keine völlig neue Textkomponentenimplementierung nötig, sondern nur eine Unterklasse der Standard-Komponente mit passendem Dokumenten-Modell. Oder soll ein Liste nur Kontrollkästen (mit Text) darstellen soll, ist das schon über die JList mit passendem Renderer und Modell möglich.
Unproblematisch ist auch, wenn sich neue Komponenten aus anderen Swing Teilkomponenten zusammenzusetzen lassen und. Dann erweitert die neue Swing-Klasse erweitert einen Container wie JPanel, der einfach die anderen Elemente wie gewünscht platziert. Möglich ist dies zum Beispiel bei einer Statuszeile, da diese nichts großartiges macht, als einfach horizontal andere Komponenten anzuordnen und einen besonderen Rahmen zu setzen. Einen Dialog zur Auswahl eines Zeichensatzes bietet Swing bisher auch nicht an, der lässt sich aber als JDialog mit passenden Swing-Komponenten leicht nachbauen.
Mehr Arbeit ist nötig, wenn sich auf keine allgemeinen Swing-Komponenten zurückgreifen lässt. Die Swing-Bibliothek bietet etwa keine Ribbon-Komponente, keinen wirklich guten HTML-Renderer, oder ein Docking-Framework. Bei Anforderungen dieser Art lässt sich nicht so einfach auf Standardkomponenten zurückgreifen, sondern spezieller Programmcode zum Zeichnen nötig. Der wesentliche Unterschied ist also der, dass sich die Darstellung nicht vollständig an Standardkomponenten delegieren lässt sondern immer etwas einer Java-Code zum Zeichnen nötig ist.
Um es richtig gut zu machen, sind für eine eigene Swing-Komponente drei Dinge nötig: Die Komponentenklasse, eine Modellklasse und ein UI-Delegate. Die Komponentenklasse ist die Hauptklasse und eine JComponent, die der Entwickler auf die Gui setzt. Sie bietet die API zum Setzten der Zustände. Die Modell-Daten werden nicht selbst in der Komponentenklasse gespeichert, sondern idealweise über eine eigene Klasse modelliert. Die Tabelle nimmt zum Beispiel die Zellen aus einem Tabellemodell, eine Textkomponenten den Text aus einem Dokumentenmodell. Als letztes bleibt der UI-Delegate, der das wirkliche Zeichen und die Ereignisbehandlung übernimmt. Es kann sehr anspruchvoll sein ein gutes Aussehen und effektive Navigation zu erreichen und insbesondere wenn die Komponente in verschiedenen Look-and-Feels arbeiten soll, eine Menge Arbeit werden. Und das die eigene Swing-Komponente die UI-Eigenschaften wie Farben, Abstände und Antialiasing-Modus toleriert ist selbstverständlich.
Überlagerungen mit dem Swing-Komponenten-Dekorator JLayer
Können Swing-Komponten überlagert werden, können dadurch interessante Effekte erzieht werden. Ein paar Beispiele:
· Während ein Text in die Textbox geladen wird, erscheint ein JProgressBar.
· Bei aufwändigen Operationen wird das Haupt-Panel gesperrt und eine drehende Sanduhr erscheint.
· Ist die Eingabe in einem Textfeld falsch, erscheint ein kleines Symbol, welches über die invalide Eingabe informiert.
· Über einer leeren Tabelle liegt eine Beschriftung, die erklärt, dass Doppelklick eine neue Zeile einfügt.
Alle die Darstellungen lassen sich mit Hilfe der in Java 7 eingefügten Klassen JLayer einfach lösen (Nutzer vor Java 7 greifen auf SwingX zurück, denn von dort kommt die Klasse auch; sie heißt nur dort JXLayer. Als Alternative haben Autoren auch oft auf Glass-Pane zurückgegriffen.)
Haupteigenschaft von JLayer ist, sich um existierende Swing-Komponenten zu legen. Soll ein JLayer um ein Textfeld gelegt werden, heißt es:
JLayer layer = new JLayer( textField );
Die zu ummantelnde Komponente wird über den Konstruktor angegeben und nicht über add(), da JLayer kein Container ist. Der nächste Schritt ist die Angabe eines Objekts, dass das Zeichnen übernimmt.
layer.setUI( layerUI );
Die Angabe erfordert ein LayerUI-Objekt, welches eine paint()-Methode realisiert. Die Implementierung kann super.paint() aufrufen, um die ummantelte Komponente zu zeichnen, und dann eigenen Programmcode hinzufügen, um etwa einen Sanduhr darzustellen.
Das folgende Beispiel fasst die Schritte zusammen und realisiert ein Programm, welches bei Eingabe von „pu“ einen kleinen roten Kreis anzeigt.
JFrame f = new JFrame();
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
f.setLayout( new BorderLayout(2, 2) );
f.add( new JSeparator(), BorderLayout.PAGE_START );
f.add( new JLabel( "Name:" ), BorderLayout.LINE_START );
final JTextField textField = new JTextField();
LayerUI layerUI = new LayerUI()
{
@Override
public void paint( Graphics g, JComponent component )
{
super.paint( g, component );
if ( textField.getText().equalsIgnoreCase( "pu" ) )
{
g.setColor( new Color( 255, 0, 0, 100 ) );
g.fillOval( 0, component.getHeight() - 10, 10, 10 );
}
}
};
JLayer layer = new JLayer( textField );
layer.setUI( layerUI );
f.add( layer );
f.add( new JSeparator(), BorderLayout.PAGE_END );
f.pack();
f.setVisible( true );
Die JLayer kann auch das Hauptpanel dekorieren und die Events auffangen. Das ist eine zweites Anwendungsfeld neben dem Änderung der Darstellung. Die JLayer-Komponente kann einfach Events auffangen und verarbeiten und so zum Beispiel global F1 für die Hilfe abfangen.
Unproblematisch ist auch, wenn sich neue Komponenten aus anderen Swing Teilkomponenten zusammenzusetzen lassen und. Dann erweitert die neue Swing-Klasse erweitert einen Container wie JPanel, der einfach die anderen Elemente wie gewünscht platziert. Möglich ist dies zum Beispiel bei einer Statuszeile, da diese nichts großartiges macht, als einfach horizontal andere Komponenten anzuordnen und einen besonderen Rahmen zu setzen. Einen Dialog zur Auswahl eines Zeichensatzes bietet Swing bisher auch nicht an, der lässt sich aber als JDialog mit passenden Swing-Komponenten leicht nachbauen.
Mehr Arbeit ist nötig, wenn sich auf keine allgemeinen Swing-Komponenten zurückgreifen lässt. Die Swing-Bibliothek bietet etwa keine Ribbon-Komponente, keinen wirklich guten HTML-Renderer, oder ein Docking-Framework. Bei Anforderungen dieser Art lässt sich nicht so einfach auf Standardkomponenten zurückgreifen, sondern spezieller Programmcode zum Zeichnen nötig. Der wesentliche Unterschied ist also der, dass sich die Darstellung nicht vollständig an Standardkomponenten delegieren lässt sondern immer etwas einer Java-Code zum Zeichnen nötig ist.
Um es richtig gut zu machen, sind für eine eigene Swing-Komponente drei Dinge nötig: Die Komponentenklasse, eine Modellklasse und ein UI-Delegate. Die Komponentenklasse ist die Hauptklasse und eine JComponent, die der Entwickler auf die Gui setzt. Sie bietet die API zum Setzten der Zustände. Die Modell-Daten werden nicht selbst in der Komponentenklasse gespeichert, sondern idealweise über eine eigene Klasse modelliert. Die Tabelle nimmt zum Beispiel die Zellen aus einem Tabellemodell, eine Textkomponenten den Text aus einem Dokumentenmodell. Als letztes bleibt der UI-Delegate, der das wirkliche Zeichen und die Ereignisbehandlung übernimmt. Es kann sehr anspruchvoll sein ein gutes Aussehen und effektive Navigation zu erreichen und insbesondere wenn die Komponente in verschiedenen Look-and-Feels arbeiten soll, eine Menge Arbeit werden. Und das die eigene Swing-Komponente die UI-Eigenschaften wie Farben, Abstände und Antialiasing-Modus toleriert ist selbstverständlich.
Überlagerungen mit dem Swing-Komponenten-Dekorator JLayer
Können Swing-Komponten überlagert werden, können dadurch interessante Effekte erzieht werden. Ein paar Beispiele:
· Während ein Text in die Textbox geladen wird, erscheint ein JProgressBar.
· Bei aufwändigen Operationen wird das Haupt-Panel gesperrt und eine drehende Sanduhr erscheint.
· Ist die Eingabe in einem Textfeld falsch, erscheint ein kleines Symbol, welches über die invalide Eingabe informiert.
· Über einer leeren Tabelle liegt eine Beschriftung, die erklärt, dass Doppelklick eine neue Zeile einfügt.
Alle die Darstellungen lassen sich mit Hilfe der in Java 7 eingefügten Klassen JLayer einfach lösen (Nutzer vor Java 7 greifen auf SwingX zurück, denn von dort kommt die Klasse auch; sie heißt nur dort JXLayer. Als Alternative haben Autoren auch oft auf Glass-Pane zurückgegriffen.)
Haupteigenschaft von JLayer ist, sich um existierende Swing-Komponenten zu legen. Soll ein JLayer um ein Textfeld gelegt werden, heißt es:
JLayer
Die zu ummantelnde Komponente wird über den Konstruktor angegeben und nicht über add(), da JLayer kein Container ist. Der nächste Schritt ist die Angabe eines Objekts, dass das Zeichnen übernimmt.
layer.setUI( layerUI );
Die Angabe erfordert ein LayerUI-Objekt, welches eine paint()-Methode realisiert. Die Implementierung kann super.paint() aufrufen, um die ummantelte Komponente zu zeichnen, und dann eigenen Programmcode hinzufügen, um etwa einen Sanduhr darzustellen.
Das folgende Beispiel fasst die Schritte zusammen und realisiert ein Programm, welches bei Eingabe von „pu“ einen kleinen roten Kreis anzeigt.
JFrame f = new JFrame();
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
f.setLayout( new BorderLayout(2, 2) );
f.add( new JSeparator(), BorderLayout.PAGE_START );
f.add( new JLabel( "Name:" ), BorderLayout.LINE_START );
final JTextField textField = new JTextField();
LayerUI
{
@Override
public void paint( Graphics g, JComponent component )
{
super.paint( g, component );
if ( textField.getText().equalsIgnoreCase( "pu" ) )
{
g.setColor( new Color( 255, 0, 0, 100 ) );
g.fillOval( 0, component.getHeight() - 10, 10, 10 );
}
}
};
JLayer
layer.setUI( layerUI );
f.add( layer );
f.add( new JSeparator(), BorderLayout.PAGE_END );
f.pack();
f.setVisible( true );
Die JLayer kann auch das Hauptpanel dekorieren und die Events auffangen. Das ist eine zweites Anwendungsfeld neben dem Änderung der Darstellung. Die JLayer-Komponente kann einfach Events auffangen und verarbeiten und so zum Beispiel global F1 für die Hilfe abfangen.

0 Antwort(en) auf ›Swing-Komponenten neu erstellen oder verändern und JLayer‹
Kommentar veröffentlichen