![]() |
|
Nachdem in diesem Kapitel die besonderen Eigenschaften der Swing-Komponenten erläutert wurden, werden im nun folgenden Teil die unterschiedlichen Swing-Komponenten erklärt. Swing bietet ebenso wie das AWT eine Menge von Klassen, mit deren Hilfe grafische Benutzeroberflächen, einschließlich der Interaktionsmöglichkeiten, die sich aus der Verwendung der Maus und der Tastatur ergeben, erstellt werden können. Die Klassen, aus denen Swing besteht, sind Teil des Packages javax.swing. Werden daher Benutzerschnittstellen in Swing implementiert, so darf das Importieren dieses Packages nicht vergessen werden.
import javax.swing.*; Wie in Kapitel 4 (Java-GUIs) beschrieben wurde, bestehen die statischen Komponenten einer Benutzerschnittstelle aus den folgenden drei Elementen:
Komponenten und Container Swing-Komponenten können in folgende Gruppen kategorisiert werden:
Abb. 8-9 veranschaulicht die Gliederung von Swing-Komponenten, die eine Entsprechung im AWT finden. In Abb. 8-10 wird die Hierarchie der Lightweight-Komponenten in Swing darstellt, in Abb. 8-11 die der Heavyweight-Komponenten.
Abb. 8.10: Klassenhierarchie der Lightweight-Komponenten in Swing Die Basisklasse javax.swing.JComponent vererbt die folgenden Eigenschaften an ihre Unterklassen:
Vergleicht man die Abbildungen 8-9 , 8-10 und 8-11 miteinander, so stellt man fest, dass es Swing-Komponenten gibt, die keine entsprechenden Gegenstücke im AWT besitzen. Diese in Swing neu eingeführten Komponenten sind in Abb. 8-12 dargestellt. Im Folgenden werden die Komponenten, die Swing bereitstellt, erläutert. Klasse JRootPane Die Klasse JRootPane stellt das Basiselement der Heavyweight-Container JFrame, JDialog, JWindow, JApplet bzw. des einzigen Lightweight-Containers JInternal-Frame dar. JRootPane setzt sich aus zwei Objekten zusammen, JGlassPane und JLayeredPane. Das JGlassPane-Objekt ist unsichtbar und dient dazu, jedes Objekt, das in ihm platziert wird, im Vordergrund anzuzeigen. JLayeredPane besteht aus zwei Objekten, einer MenuBar und einer contentPane. Ein contentPane-Objekt verhält sich wie eine reguläre AWT-Komponente. Das Hinzufügen der Komponenten zu einem der Container, der im Package javax.swing definiert ist, erfolgt anders als bei AWT-Komponenten, in denen direkt die add-Methode aufgerufen wird. Eine Komponente in Swing muss stets in den Inhaltsbereich der übergeordneten Swing-Komponente eingefügt werden.
Abb. 8.12: Swing-Komponenten, die keine Analogie zu AWT-Komponenten besitzen Die Syntax für das Setzen eines Layouts und für das Einfügen einer Komponente in einen AWT-Container lautet (siehe auch Kapitel 4 zu GUIs):
AWTKomponentenTyp.setLayout(layout); Bei der Benutzung der Swing-Komponenten hingegen wird das Setzen eines Layouts und das Einfügen einer Komponente dem Inhaltsbereich der Komponente überlassen:
SwingKomponentenTyp.getContentPane().setLayout(layout); Die wichtigsten Methoden von Swing-Containern sind:
Klasse JLayeredPane Klasse JApplet Da ein JApplet-Objekt gleichzeitig ein Heavyweight-Container ist, ist die direkte Verwendung der add-Methode innerhalb von JApplet-Objekten nicht zulässig. JApplet ist, wie in Abb. 8-11 angegeben, eine Erweiterung des Packages java.applet.Applet. Trotzdem weist die JApplet-Klasse eine geringfügige Inkompatibilität zu ihrer Elternklasse java.applet.Applet auf, da JApplet eine JRootPane-Klasse beinhaltet. Der Inhalt (child) dieser Klasse wird zur Vererbung auf jede Komponentenklasse verwendet, die eingefügt werden soll. Dies steht im Gegensatz zur Klasse java.applet.Applet.
Abb. 8.13: Die Überlappung der Standard-JLayeredPane-Schichten Das Hinzufügen einer beliebigen Komponente in einem java.applet.Applet erfolgt nach folgender Syntax:
applet.add(komponente); Im Gegensatz dazu kann eine Komponente nicht direkt in ein JApplet-Objekt eingefügt, sondern lediglich zu dessen Inhalt hinzugefügt werden, wozu die folgende Syntax zu verwenden ist:
applet.getContentPane().add(komponente); Das gleiche gilt auch für das Setzen eines Layout-Managers und das Entfernen einer Komponente mittels der remove-Methode. Standard-Layout eines contentPane()-Objekts ist das BorderLayout. Klasse JFrame JFrame stellt eine Erweiterung der Klasse java.awt.Frame dar. Das Hinzufügen von Frames zu Applets muss im AWT mit der anschließend dargestellten Syntax erfolgen:
frame.add(komponente); Ähnlich wie bei JApplet werden Komponenten nicht direkt hinzugefügt oder entfernt, sondern über ein contentPane-Objekt mittels folgender Syntax platziert:
frame.getContentPane().add(komponente); JFrame unterscheidet sich von der Elternklasse java.awt.Frame, da das Schließen eines JFrame-Objekts unterschiedlich definiert ist. Die Methode setDefaultCloseOperation() erlaubt die Definition einer Funktion, die ein Frame-Objekt schließt, und somit das Überschreiben des Standardverhaltens. Das Aufrufen der Methode
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLO SE) erlaubt es bspw., dass sich ein JFrame-Objekt auf dieselbe Weise verhält wie ein java.awt.Frame-Objekt. Die Klasse JFrame kann ebenso wie die Elternklasse Frame mit zwei Konstruktoren aufgerufen werden:
Weiterhin stellt Das folgende
import java.awt.*; public JFenster() { } public static void main(String[] args) { JFenster fenster = new JFenster(); } } Klasse JInternalFrame Mit JInternalFrame wird es möglich, innerhalb eines Panels oder eines Frames beliebige Frames zu definieren. Um JInternalFrame richtig zu verwenden, müssen die folgenden Regeln beachtet werden:
Das folgende Beispiel verdeutlicht die Anwendung von
protected void createFrame() { JInternalFrame frame = new JInternalFrame("InternalFrame#" + (++offeneFrames) frame.setLocation(20*offeneFrames,20*offeneFrames); frame.setSelected(true); } catch (java.beans.PropertyVetoException e2) {} } Der Konstruktor verwendet zusätzlich zum Titel des Frames noch vier boole'sche Variablen. Die erste Variable sagt aus, ob das JInternalFrame-Objekt in der Größe variierbar ist oder nicht. Die zweite boole'sche Variable ermöglicht es, das JInternalFrame-Objekt zu schließen. Die dritte Variable beinhaltet Informationen darüber, ob das JInternalFrame-Objekt vergrößerbar ist und die vierte Variable definiert die Möglichkeit, das JInternalFrame-Objekt zu ikonifizieren.
Abb. 8.14: JInternalFrames Im Folgenden werden die wichtigsten der oben dargestellten Regeln angewendet, die Eingabe der Größe und der Position des JInternalFrame-Objekts und das Hinzufügen des JInternalFrame-Objekts zu einer Instanz des JDesktopPane-Objekts. Der Ausdruck zwischen den Anweisungen try und catch hat keine Auswirkung auf die Generierung eines JInternalFrame-Objekts. Er sagt lediglich aus, dass das erzeugte JInternalFrame-Objekts automatisch selektiert werden soll. In Abb. 8-14 ist das Resultat dargestellt, das sich nach fünfmaliger Instantiierung von JInternal-Frame mit dem Menüpunkt neu und nach der Ikonifizierung der Frames 2, 4 und 5 ergibt. Klasse AbstractButton Die Klasse AbstractButton stellt keine Komponente dar, die direkt anwendbar ist. AbstractButton ist eine abstrakte Klasse, die das allgemeine Verhalten der folgenden Unterklassen festlegt: JButton, JToggleButton, JCheckbox und JRadioButton. Die wichtigsten Methoden der AbstractButton-Klasse sind:
Klasse JButton Das folgende
import java.awt.*; ImageIcon icon1 = new ImageIcon("left.gif"); this.getContentPane().add(start, BorderLayout.NORTH); } }
Abb. 8.15: Buttons in Swing Klasse JLabel Die Klasse JLabel ähnelt stark der AWT-Klasse java.awt.Label, bietet aber die folgende zusätzliche Funktionalität:
Zur Definition eines Das folgende
import java.awt.*; ImageIcon icon1 = new ImageIcon("left.gif"); public void init () { this.getContentPane().add(links, BorderLayout.NORTH); } }
Abb. 8.16: Textmarken in Swing Die Ausgabe dieses Beispiels ist in Abb. 8-16 dargestellt. Wie man dieser Abbildung entnehmen kann, ist das Bild immer rechts vom Text platziert. Die Klassen JCheckbox, JRadioButton und JToggleButton JToggleButton ist die Superklasse von JCheckBox und JRadioButton. Diese Klassen werden dazu verwendet, um Optionen eines Programms auswählen zu können. Die Auswahl ist hierbei nicht exklusiv, es können also auch mehrere Optionen ausgewählt werden. Soll genau eine Option auswählbar sein, so wird die Klasse JRadiobutton verwendet, die im Folgenden erklärt wird. JToggleButton und die davon abgeleiteten Komponenten werden mit den folgenden Konstruktoren erzeugt:
Die Verwendung dieser Konstruktoren entspricht exakt der Benutzung der Konstruktoren von JLabel
import java.awt.*; JCheckbox audio1 = new JCheckbox("Ton ausschalten", true); public void init () { this.getContentPane().add(audio1, BorderLayout.NORTH); } }
Abb. 8.17: Checkboxen in Swing Klasse JTextComponents JTextComponent ist eine allgemeine Textklasse, die Teil des Packages javax.swing.text ist. JTextComponent bietet alle Merkmale eines einfachen Editors an. Die wichtigsten Methoden dieser Klasse sind:
Die folgenden drei Swing-Komponenten erweitern diese Klasse: Klassen JTextField und JTextArea JTextField und JTextArea unterscheiden sich von den entsprechenden AWT-Komponenten java.awt.TextField und java.awt.TextArea nicht. Die Instantiierung eines JTextField-Objekts erfolgt mittels der Anweisung:
JTextField jtf = new JTextField(); Die Erzeugung eines neuen JTextArea-Objekts erfolgt durch:
JTextArea jta = new JTextArea(); Beide Klasse werden durch die Methode setText() initialisiert, wobei JTextArea mehrfache Zeilenangaben erlaubt:
jtf.setText("TextField"); Klasse JTextPane JTextPane stellt einen Text-Editor dar, der formatierten Text, Zeilenumbrüche und die Anzeige von Bildern unterstützt. Klasse JPasswordField JPasswordField ist eine Erweiterung von JTextField, die benutzt werden kann, um den Inhalt eines JTextField-Objekts zu maskieren. Der Asteriskus ('*') wird hierbei zur standardmäßigen Maskierung des Inhaltes verwendet. Diese Maskierung kann mittels setEchoChar() vom Programmierer geändert werden. Das folgende Code-Segment erzeugt die in Abb. 8-18 dargestellten Eingabefelder für Passwörter:
import javax.swing.*; PasswordPanel() { //Das JPasswordField-Objekt pass1 hat die standardmaessige JPasswordField pass1 = new JPasswordField(20); } public static void main(String[] args){ JFrame frame = new JFrame("Password Eingeben"); } }
Abb. 8.18: Anwendung der Klasse JPasswordField Klasse JComboBox JComboBox unterscheidet sich von der AWT-Komponente Choice dadurch, dass einige zusätzliche Methoden angeboten werden. JComboBox bietet die Möglichkeit, eine bestimmte Auswahlliste zu erweitern. Dies ist insbesondere dann nützlich, wenn das vorhandene Angebot nicht ausreichend ist. Der folgende Code erzeugt die in Abb. 8-19 dargestellten JComboPanel-Eingabefelder:
import javax.swing.*; String choices[] = {"Mercury", "Venus", "Earth", "Mars", "Saturn", "Jupiter", "Uranus","Neptune", "Pluto"}; public JComboPanel() { JComboBox combo1 = new JComboBox(); for (int i=0;i<choices.length;i++) { combo1.addItem (choices[i]); } combo2.setEditable(true); } public static void main(String[] args){ JFrame frame = new JFrame("Auswahl Liste"); } }
Abb. 8.19: Beispiel der Verwendung der Klasse JComboBox Klasse JList Die JList-Komponente unterscheidet sich von der AWT-Komponente java.awt.List dadurch, dass JList im Gegensatz zu java.awt.List keine direkte Verschiebungsfunktion anbietet. Aus programmiertechnischen Gründen muss dementsprechend JList folgendermaßen in einem ScrollPane-Objekt platziert werden:
import javax.swing.*; String label [] = {"eins", "zwei", "drei", "vier", "fünf", "sechs","sieben", "acht", "neun", "zehn" }; public JListPanel() { setLayout (new BorderLayout()); } public static void main(String[] args){ JFrame frame = new JFrame("JListPanel"); } }
Abb. 8.20: Verwendung der Klasse JList in einem ScrollPane-Objekt Klasse Border Das Package javax.swing.border beinhaltet verschiedene Objekte, um Begrenzungen um Swing-Komponenten herum zu erstellen. Die verschiedenen Border-Stile implementieren das Interface javax.swing.border.Border, das die folgenden drei Methoden beinhaltet:
Das Package Der Rand eines beliebigen
import javax.swing.*; public BorderPanel() { setLayout (new GridLayout (4, 3, 5, 5)); //Verwendung eines leeren Randes //Verwendung eines Etched-Randes //Verwendung eines gefaerbten Etched-Randes //Verwendung eines Rands mit Ueberschrift b.setBorder(new TitledBorder (new TitledBorder(LineBorder.createGrayLineBorder(),"S chiffe"), "Versenken", TitledBorder.RIGHT, TitledBorder.BOTTOM)); //Verwendung eines aufgehobenen Randes //Verwendung eines abgesetzten Randes //Verwendung eines 3-D-Randes mit weichen Ecken //Verwendung eines Randes, der das Ueberdecken einer Farbe erlaubt //Verwendung eines Randes, der das Ueberdecken eines Icons erlaubt //Verwendung eines 3-D-Randes, der aufgehoben ist } public static void main(String[] args){ JFrame frame = new JFrame("JListPanel"); } }
Abb. 8.21: Verwendung der in javax.swing.border definierten Randstile Klasse JTabbedPane JTabbedPane bietet die Möglichkeit, mehrere Panels in eine Kartei einzuordnen und damit den Zugriff auf diese Panels zu erleichtern. Eine Karte, eine sog. Card, wird einer Kartei durch die Methode addTab hinzugefügt. Diese Methode kann auf drei verschiedene Weisen aufgerufen werden:
Das
public class JTabbedPanel extends JPanel { //Titel für die zu erstellenden Tabs Durch die oben angegebenen Zeilen werden vier Tabs erstellt. Zu jedem dieser Tabs werden ein Icon (Null-Objekt) und ein Panel, das durch createPane erstellt wird, hinzugefügt.
public JTabbedPanel() { setLayout (new BorderLayout()); tabbedPane.addTab (tabs[i], null, createPane (tabs[i])); tabbedPane.setSelectedIndex(2); } createPane erstellt ein JPanel und fügt diesem ein JLabel zu, das den Titel angibt.
JPanel createPane(String s) { JPanel p = new JPanel(); } public static void main(String[] args){ JFrame frame = new JFrame("JTabbed Panel"); } }
Abb. 8.22: Anwendung der Klasse JTabbedPanel Klasse JSplitPane JSplitPane unterteilt eine Komponente in zwei weitere Komponenten. Die Größe jeder dieser Komponenten wird vom Benutzer interaktiv angepasst. Die zwei Komponenten können sowohl horizontal mit JSplitPane.HORIZONTAL_SPLIT als auch vertikal mit JSplitPane.VERTICAL_SPLIT ausgerichtet werden. JSplitPane kann mit anderen JSplitPane-Komponenten verschachtelt werden, bis das gewünschte Aussehen erreicht wird. Die Methode setContinuousLayout(boolean) veranlasst, dass jedes Teil-Panel aktualisiert wird, wenn die Größe eines Teils geändert wird. Das folgende Beispiel definiert zwei JSplitPane-Objekte und drei JButton-Objekte:
private JSplitPane splitPane, splitPaneBottom; splitPane wird in horizontaler, splitPaneBottom in vertikaler Richtung unterteilt. Diese Unterteilung wird durch den folgenden Code erreicht:
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); Dem oberen Teil von splitPane wird anschließend das Objekt topButton hinzugefügt. In splitPaneBottom werden jeweils links und rechts leftButton und rightButton hinzugefügt. Anschließend wird dieses Panel dem unteren Teil von splitPane hinzugefügt.
splitPane.setTopComponent(topButton); Durch die folgenden Methoden wird das Expandieren der einzelnen Panel-Objekte mit einem Mausklick auf das Dreieck (siehe Abb. 8-23) gewährleistet.
splitPane.setOneTouchExpandable(true);
Abb. 8.23: Anwendung der Klasse JSplitPane Klasse JTable JTable unterstützt die Anordnung von Komponenten in Tabellenform. JTable ist derart eine GUI-Komponente, anhand derer Daten im zweidimensionalen Tabellenformat präsentiert werden können. JTable erlaubt dem Benutzer auf einfache Art und Weise, Daten zu editieren bzw. Daten abzufragen. Die Spalten und Zeilen einer derartigen Tabelle werden durch ganzzahlige Werte adressiert. Durch die Methode getValueAt(int, int) wird der Wert einer Zelle abgefragt und in der Tabellenansicht dargestellt. JTable unterstützt Scroll-Objekte nicht direkt, weshalb es empfehlenswert ist, ein JTable-Objekt einem JScrollPane-Objekt hinzuzufügen. JTable verfügt u. a. über die folgenden Konstruktoren:
Um deren Funktionsweise zu verdeutlichen, wird die folgende Datenstruktur definiert: {"Julia","Java",new Integer(25),"Squatch",new Boolean(false)}, {"Abed", "Mustermann", new Integer(29),"Soccer", new Boolean(true)}, {"stefi", "Walrath", new Integer(29), "Soccer",new Boolean(true)}, {"Mark", "Andrews", new Integer(20), "Soccer",new Boolean(true)}, }; String[] columnNames = {"Name","Vorname","Alter","Sport", "Maennlich"}; Somit kann die Tabelle wie folgt instantiiert werden:
JTable tabelle = new JTable(daten, columnNames); Nun soll diese Tabelle einem JScrollPane-Objekt hinzugefügt werden. Dies geschieht mit Hilfe folgender Programmzeile:
JScrollPane scrollPane = new JScrollPane(tabelle); JScrollPane erkennt automatisch die Namen der Spalten und platziert sie an der geeigneten Stelle. Alle Spalten einer JTable weisen die gleiche Breite auf. Wenn eine bestimmte Spalte eine andere Größe haben soll, so muss dies explizit angegeben werden. Das folgende Code-Fragment bewirkt, dass die dritte Spalte kleiner als die anderen erscheint:
TableColumn column = null; column = table.getColumnModel().getColumn(i); column.setPreferredWidth(50); } else { column.setPreferredWidth(100); } } Im Folgenden wird ein Datenmodell für die Tabelle erstellt:
class meinDatenModell extends AbstractTableModel() { final String[] columnNames = ...//von oben... final Object[][] daten = ...//von oben... public String getColumnName(int col) { return columnNames[col].toString(); } public int getRowCount() { return rowData.length; } public int getColumnCount() { return columnNames.length; } public Object getValueAt(int row, int col) { return rowData[row][col]; } public boolean isCellEditable(int row, int col) { return true; } public void setValueAt(Object value, int row, int col) { rowData[row][col] = value; } } Um Änderungen der Zellen zu erkennen, wird das Interface TableModelListener implementiert:
class TML implements TableModelListener { public void tableChanged(TableModelEvent e) { for(int i = 0; i < data.length; i++) { for(int j = 0; j < data[0].length; j++) System.out.print(data[i][j] + " "); System.out.println(); } } } Anschließend wird ein Listener hinzugefügt (zur Event-Verarbeitung siehe das nachfolgende Teilkapitel).
meinDatenModell() { addTableModelListener(new TML()); } Sollen die Werte der vierten Spalte aus einer JComboBox gewählt werden, so wird folgender Code benötigt:
TableColumn sportColumn = table.getColumnModel().getColumn(3); Das Resultat dieser Anwendung ist in Abb. 8-24 dargestellt.
Abb. 8.24: Ein einfaches JTable-Beispiel Klasse JTree Die Klasse JTree dient der Darstellung eines hierarchischen Baums von Elementen. JTree ist eine Komponente, mit der bestimmte Informationen (Knoten und Blätter) am Bildschirm in einer Baumstruktur sichtbar gemacht werden können. Die in JTree dargestellten Informationen (Modell) werden mit einem sog. TreeModel beschrieben, das aus TreeNodes besteht. Für die meisten Anwendungsfälle werden die Klassen DefaultTreeModel und DefaultMutableTreeNode verwendet. Die Darstellung von TreeNodes in JTree (also in der View) erfolgt mit einem TreeCellRenderer. Die Steuerung der Aktionen, die der Benutzer mit einem JTree durchführt (also der Controller), bspw. durch Auswahl oder durch Doppelklick auf Elemente, erfolgt mit dem in diesen Klassen vorgesehenen Event-Handling. Weiterhin generieren die Methoden von TreeModel eigene Events, die dafür sorgen, dass sich die Darstellung im JTree ändert, wenn sich die Daten in TreeModel ändern. Das folgende Beispiel, dessen Ausgabe in Abb. 8-25 dargestellt ist, verdeutlicht das Arbeiten mit der Klasse JTree:
//Die Klasse Branch akzeptiert einen Array und class Branch { DefaultMutableTreeNode r; r = new DefaultMutableTreeNode(data[0]); r.add(new DefaultMutableTreeNode(data[i])); } public DefaultMutableTreeNode node() { return r; } } public class JTrees extends JPanel { //Definition der Elemente von JTree static int i = 0; setLayout(new BorderLayout()); Ein Jtree-Objekt besitzt nicht automatisch eine ScrollBar-Funktion, weshalb JTree einem JScrollBar-Objekt hinzugefügt werden muss.
add(new JScrollPane(tree),BorderLayout.CENTER); //Definition eines JTree-Modells und eines JButtons, damit Eine innere ActionListener-Klasse wird mit dem folgenden Code erstellt:
test.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ if(i < data.length) { child = new Branch(data[i++]).node(); // Wurde bereits geklickt? // tree update } } }); Nachdem die Vorder- und Hintergrundfarbe des JButton-Objekts festgelegt wurden, wird dieses in ein JPanel eingefügt.
test.setBackground(Color.blue); } public static void main(String args[]) { JFrame frame = new JFrame("JTree in Aktion"); } }
Abb. 8.25: JTree-Objekt in Swing |
|
|