|
Modale Dialoge sind solche, die alle Benutzereingaben des Programmes beanspruchen und andere Fenster erst dann wieder zum Zuge kommen lassen, wenn das Dialogfenster geschlossen wird. Eine wichtige Eigenschaft modaler Dialoge ist es, daß im Programm der Aufruf zur Anzeige des Dialogs so lange blockiert, bis der Dialog beendet ist. Auf diese Weise kann an einer bestimmten Stelle im Programm auf eine Eingabe gewartet werden und erst dann mit der Bearbeitung fortgefahren werden, wenn die Eingabe erfolgt ist.
Im AWT des JDK 1.0 gab es einen schwerwiegenden Fehler, durch den das Erzeugen modaler Dialoge unmöglich gemacht wurde. Der Fehler hielt sich bis zur Version 1.0.2 und wurde erst mit Erscheinen des JDK 1.1 behoben. Da viele Anwenderdialoge von Natur aus modalen Charakter haben, wurde dieser Fehler von vielen als schwerwiegend angesehen, und die Java-Gemeinde entwickelte eine Reihe von Workarounds, die aber allesamt nicht voll zufriedenstellen konnten. Glücklicherweise wurden die Probleme mit dem JDK 1.1 behoben, und wir wollen in diesem Kapitel aufzeigen, wie modale Dialoge in Java erzeugt werden können.
Ein modaler Dialog muß immer aus der Klasse Dialog abgeleitet werden. Nur sie bietet die Möglichkeit, an den Konstruktor einen booleschen Wert zu übergeben, der festlegt, daß die übrigen Fenster der Anwendung während der Anzeige des Dialogs suspendiert werden. Dialog besitzt folgende Konstruktoren:
public Dialog(Frame owner) public Dialog(Frame owner, boolean modal) public Dialog(Frame owner, String title) public Dialog(Frame owner, String title, boolean modal) public Dialog(Dialog owner) public Dialog(Dialog owner, String title) public Dialog(Dialog owner, String title, boolean modal) |
java.awt.Dialog |
Als erstes Argument muß in jedem Fall ein Frame- oder Dialog-Objekt als Vaterfenster übergeben werden (bis zur Version 1.1 waren nur Frame-Objekte erlaubt). Mit title kann der Inhalt der Titelzeile vorgegeben werden, und der Parameter modal entscheidet, ob der Dialog modal dargestellt wird oder nicht.
Dialog bietet die Methoden isModal und setModal, mit denen auf die Modalität des Dialogs zugegriffen werden kann:
public boolean isModal() public void setModal(boolean b) |
java.awt.Dialog |
Der Rückgabewert von isModal ist true, falls der Dialog modal ist. Andernfalls ist er false.
Die Methode setModal, deren Fähigkeit darin besteht, einen bestehenden Dialog zwischen den Zuständen modal und nicht-modal umzuschalten, ist mit Vorsicht zu genießen. Unter Windows 95 hat ein Aufruf im JDK 1.1 mitunter dazu geführt, daß beim Schließen des Fensters die Nachrichtenschleife des Aufrufers deaktiviert blieb und das Programm sich aufhängte. Am besten, man entscheidet schon im Konstruktor, ob der Dialog modal sein soll oder nicht. |
![]() |
|
![]() |
Ein zusätzliches Feature der Klasse Dialog besteht darin, die Veränderbarkeit der Größe eines Fensters durch den Anwender zu unterbinden:
public void setResizable(boolean resizable) public boolean isResizable() |
java.awt.Dialog |
Nach einem Aufruf von setResizable mit false als Argument kann die Größe des Fensters nicht mehr vom Anwender verändert werden. Nach einem Aufruf von setResizable(true) ist dies wieder möglich. Mit isResizable kann der aktuelle Zustand dieses Schalters abgefragt werden.
Auch die Methode setResizable ist nicht ganz unkritisch, denn sie hat auf einigen UNIX-Systemen zu Problemen geführt. Sowohl unter SUN Solaris als auch unter LINUX kam es im JDK 1.1 zu Hängern bei Programmen, die diese Methode benutzten. Falls sich die nachfolgenden Beispielprogramme auf Ihrem System nicht so verhalten wie angegeben (typischerweise wird der Dialog gar nicht erst angezeigt), sollten Sie versuchsweise den Aufruf von setResizable auskommentieren. |
![]() |
|
![]() |
Das folgende Beispiel demonstriert die Anwendung der Klasse Dialog. Es zeigt einen Frame, aus dem per Buttonklick ein modaler Dialog aufgerufen werden kann. Der Dialog fragt den Anwender, ob die Anwendung beendet werden soll und wartet, bis einer der Buttons »Ja« oder »Nein« gedrückt wurde. In diesem Fall wird ein boolescher Rückgabewert generiert, der nach dem Schließen des Dialogs an das Vaterfenster zurückgegeben wird. Falls der Rückgabewert true (entprechend dem Button »Ja«) ist, wird die Anwendung beendet, andernfalls läuft sie weiter:
|
![]() |
|
![]() |
Um den Dialog relativ zur Position seines Vaterfensters anzuzeigen, wird dessen Position durch Aufruf von getLocation ermittelt. Der Ursprung des Dialogfensters wird dann 30 Pixel weiter nach unten bzw. nach rechts gelegt. |
![]() |
|
![]() |
Nach dem Start zeigt das Programm zunächst das in Abbildung 21.14 dargestellte Fenster an:
Abbildung 21.14: Das Vaterfenster für den modalen Dialog
Nach dem Klick auf »Ende« wird actionPerformed aufgerufen und läuft bis zum Aufruf des Dialogs (siehe Abbildung 21.15). Die Anweisung dlg.setVisible(true); ruft den Dialog auf und blockiert dann. Sie terminiert erst, wenn der Dialog durch Drücken eines Buttons beendet wurde. In diesem Fall wird mit getResult der Rückgabewert abgefragt und das Programm beendet, wenn dieser true ist. Die Methode getResult liefert den Inhalt der privaten Instanzvariablen result, die beim Auftreten eines Action-Events durch einen der beiden Buttons gesetzt wird. Zwar ist das Dialogfenster beim Aufruf von getResult bereits zerstört, aber die Objektvariable dlg existiert noch und getResult kann aufgerufen werden.
Abbildung 21.15: Ein einfacher Ja-/Nein-Dialog
Bevor wir das Kapitel beenden, wollen wir dieses Programm ein wenig
erweitern und ein weiteres Beispiel für die Anwendung modaler
Dialoge geben. Das folgende Programm implementiert eine Klasse ModalDialog,
die aus Dialog
abgeleitet ist. Mit ihrer Hilfe können modale Dialoge der obigen
Art konstruiert werden, bei denen die Ausstattung mit Buttons variabel
ist und zum Zeitpunkt der Instanzierung festgelegt werden kann:
|
![]() |
|
![]() |
Der Konstruktor erwartet neben dem Vater-Frame drei weitere Parameter, title, msg und buttons. In title wird der Inhalt der Titelzeile übergeben, und msg spezifiziert den Text innerhalb des Dialogs. Der Parameter buttons erwartet eine Liste von Button-Bezeichnern, die zur Festlegung der Anzahl und Beschriftung der Buttons dienen. Die einzelnen Elemente sind durch Kommata zu trennen und werden innerhalb des Dialogs mit einem StringTokenizer zerlegt. Der in getResult gelieferte Rückgabewert des Dialogs ist - anders als im vorigen Beispiel - ein String und entspricht der Beschriftung des zum Schließen verwendeten Buttons.
ModalDialog enthält einige statische Methoden, mit denen Dialoge mit einer festen Buttonstruktur einfach erzeugt werden können. So erzeugt OKButton lediglich einen Button mit der Beschriftung »OK«, YesNoDialog zwei Buttons, »Ja« und »Nein«, und YesNoCancelDialog erzeugt einen Dialog mit drei Buttons, »Ja«, »Nein« und »Abbruch«. Das folgende Listing zeigt die Klasse ModalDialog und ein Rahmenprogramm zum Testen: |
![]() |
|
![]() |
001 /* Listing2111.java */ 002 003 import java.awt.*; 004 import java.awt.event.*; 005 import java.util.*; 006 007 class ModalDialog 008 extends Dialog 009 implements ActionListener 010 { 011 String result; 012 013 public static String OKDialog(Frame owner, String msg) 014 { 015 ModalDialog dlg; 016 dlg = new ModalDialog(owner,"Nachricht",msg,"OK"); 017 dlg.setVisible(true); 018 return dlg.getResult(); 019 } 020 021 public static String YesNoDialog(Frame owner, String msg) 022 { 023 ModalDialog dlg; 024 dlg = new ModalDialog(owner,"Frage",msg,"Ja,Nein"); 025 dlg.setVisible(true); 026 return dlg.getResult(); 027 } 028 029 public static String YesNoCancelDialog(Frame owner,String msg) 030 { 031 ModalDialog dlg; 032 dlg = new ModalDialog(owner,"Frage",msg,"Ja,Nein,Abbruch"); 033 dlg.setVisible(true); 034 return dlg.getResult(); 035 } 036 037 public ModalDialog( 038 Frame owner, 039 String title, 040 String msg, 041 String buttons 042 ) 043 { 044 super(owner, title, true); 045 //Fenster 046 setBackground(Color.lightGray); 047 setLayout(new BorderLayout()); 048 setResizable(false); 049 Point parloc = owner.getLocation(); 050 setLocation(parloc.x + 30, parloc.y + 30); 051 //Message 052 add("Center", new Label(msg)); 053 //Buttons 054 Panel panel = new Panel(); 055 panel.setLayout(new FlowLayout(FlowLayout.CENTER)); 056 StringTokenizer strtok = new StringTokenizer(buttons,","); 057 while (strtok.hasMoreTokens()) { 058 Button button = new Button(strtok.nextToken()); 059 button.addActionListener(this); 060 panel.add(button); 061 } 062 add("South", panel); 063 pack(); 064 } 065 066 public void actionPerformed(ActionEvent event) 067 { 068 result = event.getActionCommand(); 069 setVisible(false); 070 dispose(); 071 } 072 073 public String getResult() 074 { 075 return result; 076 } 077 } 078 079 public class Listing2111 080 extends Frame 081 implements ActionListener 082 { 083 public static void main(String[] args) 084 { 085 Listing2111 wnd = new Listing2111(); 086 wnd.setVisible(true); 087 } 088 089 public Listing2111() 090 { 091 super("Drei modale Standarddialoge"); 092 setLayout(new FlowLayout()); 093 setBackground(Color.lightGray); 094 Button button = new Button("OKDialog"); 095 button.addActionListener(this); 096 add(button); 097 button = new Button("YesNoDialog"); 098 button.addActionListener(this); 099 add(button); 100 button = new Button("YesNoCancelDialog"); 101 button.addActionListener(this); 102 add(button); 103 setLocation(100,100); 104 setSize(400,200); 105 setVisible(true); 106 } 107 108 public void actionPerformed(ActionEvent event) 109 { 110 String cmd = event.getActionCommand(); 111 if (cmd.equals("OKDialog")) { 112 ModalDialog.OKDialog(this,"Dream, dream, dream, ..."); 113 } else if (cmd.equals("YesNoDialog")) { 114 String ret = ModalDialog.YesNoDialog( 115 this, 116 "Programm beenden?" 117 ); 118 if (ret.equals("Ja")) { 119 setVisible(false); 120 dispose(); 121 System.exit(0); 122 } 123 } else if (cmd.equals("YesNoCancelDialog")) { 124 String msg = "Verzeichnis erstellen?"; 125 String ret = ModalDialog.YesNoCancelDialog(this,msg); 126 ModalDialog.OKDialog(this,"Rückgabe: " + ret); 127 } 128 } 129 } |
Listing2111.java |
Die drei Dialoge, die durch Aufrufe von OKDialog, YesNoDialog und YesNoCancelDialog generiert werden, sind in den folgenden Abbildungen 21.16 bis 21.18 dargestellt:
Abbildung 21.16: Ein Aufruf von OKDialog
Abbildung 21.17: Ein Aufruf von YesNoDialog
Abbildung 21.18: Ein Aufruf von YesNoCancelDialog
|
Go To Java 2, Addison Wesley, Version 1.0.2, © 1999 Guido Krüger, http://www.gkrueger.com |