16.21 Dialoge und Window-Objekte 

Seit den ersten Swing-Tagen besitzt Swing Standard-Dialoge wie einen Dateiauswahl-, Druck- oder Farbauswahldialog, aber auch viele interessante Dialoge sind als quelloffene Komponenten verfügbar. Dazu zählen etwa ein Dialog zur Auswahl von Zeichensätzen oder Verzeichnissen (etwa bei http://common.l2fprod.com/) oder Wizards (http://xito.sourceforge.net/projects/dialog/index.php).
16.21.1 JWindow und JDialog 

Ein JFrame ist ein Fenster, das standardmäßig eine Dekoration besitzt. Ein java.awt.Window hat diese Dekoration nicht, sodass sich diese Fläche als Willkommensbildschirm oder als komplette Zeichenfläche nutzen lässt. javax.swing.JWindow ist die Swing-Unterklasse von Window.
Die folgende Tabelle gibt die Unterschiede zwischen Fenster, Window und Dialog an:
Eigenschaft | Fenster | Window | Dialog |
modal |
nein |
nein |
möglich |
größenveränderbar |
ja |
nein |
ja |
Titel |
ja |
nein |
ja |
Rahmen |
ja |
nein |
ja |
Menü |
ja |
nein |
unüblich, bei JDialog aber möglich |
Symbol-Icon |
ja |
nein |
mit Hack [((Frame) dialog.getOwner()).setIconImage(image);] ja |
16.21.2 Modal oder nicht-modal 

Bildet eine Java-Applikation zwei Fenster, so kann der Anwender zwischen beiden Fenstern hin- und herschalten. Es ist nicht möglich, ein Fenster aufzubauen und dort Eingaben zu erzwingen, während das andere Fenster gesperrt ist. Dafür gibt es in Java spezielle Fenster, die Dialoge, die Swing mit javax.swing.JDialog angeht. JDialog ist eine Unterklasse von der AWT-Klasse Dialog, und Dialog ist wiederum eine Spezialisierung von Window. Ist ein Dialog im Zustand modal, muss erst der Dialog beendet werden, damit es in einem anderen Fenster weitergehen kann – alle Benutzereingaben an andere Fenster der Java-Anwendung sind so lange gesperrt. Sind mehrere Fenster gleichzeitig offen und können sie Eingaben annehmen, nennt sich dieser Zustand nicht-modal.
Soll der Dialog modal sein, sind ein übergeordnetes Fenster und ein Wahrheitswert true für den Modalitätstyp einzusetzen.
JDialog d = new JDialog( owner, true ); ... d.setVisible( true ); // Hier geht’s erst nach dem Schließen des Dialogs weiter.
Der owner kann ein anderer Dialog, ein Frame oder ein Window sein. Da bei modalen Dialogen alle Eingaben zu anderen Fenstern blockiert sind, nehmen erst nach dem Schließen des Dialogs andere Fenster die Eingaben wieder an.
16.21.3 Standarddialoge mit JOptionPane 

Die Klasse JOptionPane erlaubt einfache Meldedialoge, Eingabedialoge, Bestätigungsdialoge und Optionsdialoge mit nur einem statischen Funktionsaufruf der Art showXXXDialog(). Einige Beispiele:
Listing 16.65 com/tutego/insel/ui/dialog/JOptionPaneDialogDemo.java, main()
// Dialog for a simple message JOptionPane.showMessageDialog( null, "Wir Kinder aus dem Möwenweg" ); // Dialog for a user input JOptionPane.showInputDialog( "Bitte Zahl eingeben" ); // Dialog to confirm a choice JOptionPane.showConfirmDialog( null, "Alles OK?" ); // Dialog with different choices String[] genderOptions = { "männlich", "weiblich", "keine Ahnung", "ändert sich ständig" }; String gender = (String) JOptionPane.showInputDialog( null, "Geschlecht", "Bitte das Geschlecht wählen (eigenes, nicht gewünschtes)", JOptionPane.QUESTION_MESSAGE, null, genderOptions, genderOptions[1] ); System.out.println( gender ); // Customized option dialog String[] yesNoOptions = { "Ja", "Nein", "Abbrechen" }; int n = JOptionPane.showOptionDialog( null, "Ja oder Nein?", // question "Ja/Nein/Abbrechen", // title JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, // icon null, yesNoOptions,yesNoOptions[0] ); if ( n == JOptionPane.YES_OPTION ) System.out.println("Ja gewählt"); System.exit( 0 );
Einige Funktionen erwarten als erstes Argument eine Vater-Komponente, die null sein kann. Sie dient zur relativen Ausrichtung des Dialogs und verknüpft den Dialog derart mit einem Fenster, dass, wenn das Fenster versteckt wird, auch der Dialog verschwindet.
Die Funktion showConfirmDialog() ist sehr flexibel, denn sie erlaubt die Angabe für Icon, Überschrift, Fragetext und Beschriftung der Schaltflächen. Bei den Funktionen showMessageDialog(), showConfirmDialog() und showOptionDialog() zeigt eine Rückgabe an, was der Benutzer gewählt hat. Mögliche Rückgaben sind Ganzzahlen, die die Konstanten YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION oder CLOSED_OPTION benennen. Die drei Funktionen und showInputDialog() erlauben zusätzlich die Angabe eines Nachrichtentyps; mögliche Konstanten sind ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE und PLAIN_MESSAGE. Sie bestimmen im Allgemeinen ein Standard-Icon.
Selten gibt es die Notwendigkeit, nicht die statischen Funktionen showXXXDialog() einzusetzen. Erforderlich kann ein Exemplar der Klasse JOptionPane aber dann sein, wenn zum Beispiel beim Klick auf das × vom Dialog-Fenster der Dialog nicht verschwinden soll oder wenn zum Beispiel gewisse Werte im Textfeld bei showInputDialog() nicht erwünscht sind, wie Folgen von Leerzeichen. Grundsätzlich sieht der Aufbau eines eigenen Dialogs dann so aus:
JOptionPane pane = new JOptionPane( ... ); JDialog dialog = new JDialog(); dialog.setContentPane( pane );
oder:
JOptionPane pane = new JOptionPane( ... ); JDialog dialog = pane.createDialog( parent, title );
16.21.4 Der Dateiauswahldialog 

Die Klasse JFileChooser (unter AWT heißt die Klasse FileDialog) simuliert einen betriebssystemabhängigen Dialog zur Auswahl von Dateien und Verzeichnissen. Der Selektor ist modal und kann für das Speichern und Öffnen konfiguriert sein. Zudem lassen sich die Pfade und ein javax.swing.filechooser.FileFilter zur Auswahl spezieller Dateien setzen. Erst nach dem Schließen und Beenden mit dem OK-Button stehen ausgewählte Dateien zur Verfügung.
Beispiel Einen Dateiauswahldialog auf den Schirm bringen: JFileChooser fc = new JFileChooser(); int state = fc.showOpenDialog( null ); Die gewählte Datei erfragt getSelectedFile(), und die Rückgabe ist JFileChooser. APPROVE_OPTION, JFileChooser.CANCEL_OPTION oder JFileChooser.ERROR_OPTION. |
Vollständiges Programm für eine Auswahlbox
Wir können direkt aus dem Hauptprogramm ein Objekt JFrame erzeugen und dann einen Dateiauswahldialog öffnen. Zusätzlich wollen wir ihm einen Filter mitgeben, der alle Dateien mit der Endung .txt aussondert. Zudem soll unser Filter alle Verzeichnisse zulassen. Die Realisierung des Filterns erfolgt durch die Implementierung der Schnittstelle FileFilter. Obwohl wir eine Schnittstelle unter diesem Namen schon kennen, handelt es sich nicht um diejenige aus dem java.io-Paket, sondern um eine Schnittstelle aus dem Paket javax. swing.filechooser.
Die die Schnittstelle FileFilter implementierenden Klassen müssen eine accept()-Methode realisieren und eine Methode getDescription(), die eine Zeichenkette liefert.
Listing 16.66 com/tutego/insel/ui/dialog/JFileChooserDemo.java
package com.tutego.insel.ui.dialog; import java.io.File; import javax.swing.*; import javax.swing.filechooser.FileFilter; public class JFileChooserDemo { public static void main( String[] args ) { JFileChooser fc = new JFileChooser(); fc.setFileFilter( new FileFilter() { @Override public boolean accept( File f ) { return f.isDirectory() || f.getName().toLowerCase().endsWith( ".txt" ); } @Override public String getDescription() { return "Texte"; } } ); int state = fc.showOpenDialog( null ); if ( state == JFileChooser.APPROVE_OPTION ) { File file = fc.getSelectedFile(); System.out.println( file.getName() ); } else System.out.println( "Auswahl abgebrochen" ); System.exit( 0 ); } }
Abbildung 16.21 Der Dateiauswahldialog
Tipp Im Speichern-Dialog ist ein Standardname anzugeben. Im Idealfall richtet er sich nach dem Inhalt der Datei. Dazu bietet die Klasse JFileChooser die Methode setSelectedFile(). c.setSelectedFile( new File("c:/test.txt") ); |
class javax.swing.JFileChooser
extends JComponent
implements Accessible |
Zum Erzeugen eines Auswahldialogs steht eine Reihe von Konstruktoren zur Auswahl:
- JFileChooser()
Erzeugt einen Dateidialog ohne Titel zum Öffnen einer Datei. Zeigt auf das Benutzerverzeichnis.
- JFileChooser( File currentDirectory )
Wie JFileChooser(), aber zeigt beim Start auf das Verzeichnis currentDirectory.
- JFileChooser( String currentDirectoryPath )
Wie JFileChooser( new File(currentDirectoryPath) ).
- String getDirectory()
Liefert das Dialogverzeichnis.
- File getSelectedFile()
Liefert die ausgewählte Datei.
- File[] getSelectedFiles()
Liefert alle ausgewählten Dateien, wenn der Dateiauswahldialog Mehrfachselektion zulässt.
- void setDialogTitle( String dialogTitle )
Setzt einen neuen Fenstertitel.
- void setDialogType( int dialogType )
Handelt es sich um einen Laden-/Speichern-Dialog oder um einen angepassten Dialog? Deklarierte Konstanten sind JFileChooser.OPEN_DIALOG, JFileChooser.SAVE_DIALOG und JFileChooser.CUSTOM_DIALOG.
- void setFileFilter( javax.swing.filechooser.FileFilter filter )
Setzt einen FileFilter zur Anzeige der gewünschten Dateien.
- void setFileHidingEnabled( boolean b )
Bestimmt, ob verborgene Dateien angezeigt werden sollen.
- void setFileView( FileView fileView )
Standardmäßig zeigt der Dialog neben dem Dateinamen ein kleines Bild an. Das lässt sich mit einem einen FileView-Objekt anpassen.
- void setAccessory( JComponent newAccessory )
Setzt eine Komponente für eine mögliche Vorschau.
Hinweis Sollen im Dialog nur Verzeichnisse, aber keine Dateien auftauchen, so lässt sich dies mit setFileSelectionMode() und einem passenden Argument einstellen. fileChooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY ); Insgesamt sind drei Konstanten deklariert: FILES_ONLY, DIRECTORIES_ONLY und FILES_AND_ DIRECTORIES. Der Name verrät schon die Bedeutung. |
Ein konkreter Filter implementiert die Schnittstelle javax.swing.filechooser.FileFilter.
abstract class javax.swing.filechooser.FileFilter |
- abstract boolean accept( File f )
Akzeptiert der FileFilter die Datei oder nicht?
- abstract String getDescription()
Liefert eine Beschreibung für den Filter.
Vorschaubilder
Die Methode setAccessory() kann eine JComponent für die Vorschau zuweisen, die immer dann aktualisiert wird, wenn der Benutzer im Dialog eine Datei auswählt. Eine Auswahl meldet dabei ein PropertyChangeEvent, das ein Listener abfängt und testet, ob es JFileChooser.SELECTED_FILE_CHANGED_PROPERTY war. Um das Vorgehen kurz zu skizzieren, folgende Ereignisbehandlung:
public void propertyChange( PropertyChangeEvent e ) { if ( JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(e.getPropertyName()) ) { File f = (File) e.getNewValue(); // File f laden, etwa mit ImageIcon, dann anzeigen. } }