From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+Modale Dialoge sind solche, die alle Benutzereingaben des Programms
+beanspruchen und andere Fenster erst dann wieder zum Zuge kommen lassen,
+wenn das Dialogfenster geschlossen wird. Eine wichtige Eigenschaft
+modaler Dialoge ist es, dass 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 muss immer aus der Klasse Dialog
+abgeleitet werden. Nur sie bietet die Möglichkeit, an den Konstruktor
+einen booleschen Wert zu übergeben, der festlegt, dass die übrigen
+Fenster der Anwendung während der Anzeige des Dialogs suspendiert
+werden. Dialog
+besitzt folgende Konstruktoren:
+
+
+Als erstes Argument muss 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:
+
+
+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, dass 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:
+
+
+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:
+
+
+
+
+
+
+ Titel
+ Inhalt
+ Suchen
+ Index
+ DOC
+ Handbuch der Java-Programmierung, 5. Auflage
+
+ <<
+ <
+ >
+ >>
+ API
+ Kapitel 31 - GUI-Dialoge
+
+
+
+
+
+31.3 Modale Dialoge
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+public boolean isModal()
+
+public void setModal(boolean b)
+
+
+
+java.awt.Dialog
+
+
+
+
+
+
+
+![]()
+
+![]()
+
+
+
+![]()
+
+
+
+
+
+ Warnung
+
+
+
+
+
+
+
+
+
+
+public void setResizable(boolean resizable)
+
+public boolean isResizable()
+
+
+
+java.awt.Dialog
+
+
+
+
+
+
+
+![]()
+
+![]()
+
+
+
+![]()
+
+
+
+
+
+ Warnung
+
+
+
+
+Listing 31.10: Konstruktion modaler Dialoge
+
+
+
+
+
+001 /* Listing3110.java */
+002
+003 import java.awt.*;
+004 import java.awt.event.*;
+005
+006 class YesNoDialog
+007 extends Dialog
+008 implements ActionListener
+009 {
+010 boolean result;
+011
+012 public YesNoDialog(Frame owner, String msg)
+013 {
+014 super(owner, "Ja-/Nein-Auswahl", true);
+015 //Fenster
+016 setBackground(Color.lightGray);
+017 setLayout(new BorderLayout());
+018 setResizable(false); //Hinweis im Text beachten
+019 Point parloc = owner.getLocation();
+020 setLocation(parloc.x + 30, parloc.y + 30);
+021 //Message
+022 add(new Label(msg), BorderLayout.CENTER);
+023 //Buttons
+024 Panel panel = new Panel();
+025 panel.setLayout(new FlowLayout(FlowLayout.CENTER));
+026 Button button = new Button("Ja");
+027 button.addActionListener(this);
+028 panel.add(button);
+029 button = new Button("Nein");
+030 button.addActionListener(this);
+031 panel.add(button);
+032 add(panel, BorderLayout.SOUTH);
+033 pack();
+034 }
+035
+036 public void actionPerformed(ActionEvent event)
+037 {
+038 result = event.getActionCommand().equals("Ja");
+039 setVisible(false);
+040 dispose();
+041 }
+042
+043 public boolean getResult()
+044 {
+045 return result;
+046 }
+047 }
+048
+049 public class Listing3110
+050 extends Frame
+051 implements ActionListener
+052 {
+053 public static void main(String[] args)
+054 {
+055 Listing3110 wnd = new Listing3110();
+056 wnd.setVisible(true);
+057 }
+058
+059 public Listing3110()
+060 {
+061 super("Modale Dialoge");
+062 setLayout(new FlowLayout());
+063 setBackground(Color.lightGray);
+064 Button button = new Button("Ende");
+065 button.addActionListener(this);
+066 add(button);
+067 setLocation(100,100);
+068 setSize(300,200);
+069 setVisible(true);
+070 }
+071
+072 public void actionPerformed(ActionEvent event)
+073 {
+074 String cmd = event.getActionCommand();
+075 if (cmd.equals("Ende")) {
+076 YesNoDialog dlg;
+077 dlg = new YesNoDialog(
+078 this,
+079 "Wollen Sie das Programm wirklich beenden?"
+080 );
+081 dlg.setVisible(true);
+082 //Auf das Schließen des Dialogs warten...
+083 if (dlg.getResult()) {
+084 setVisible(false);
+085 dispose();
+086 System.exit(0);
+087 }
+088 }
+089 }
+090 }
+
+
+Listing3110.java
+
+
![]() |
+
+
+ +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 31.14 +dargestellte Fenster an: +
+ +
+Abbildung 31.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 31.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 31.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:
+
+
+public ModalDialog(
+ Frame owner,
+ String title,
+ String msg,
+ String buttons
+);
+
+
+
+
+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 /* Listing3111.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(new Label(msg), BorderLayout.CENTER);
+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(panel, BorderLayout.SOUTH);
+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 Listing3111
+080 extends Frame
+081 implements ActionListener
+082 {
+083 public static void main(String[] args)
+084 {
+085 Listing3111 wnd = new Listing3111();
+086 wnd.setVisible(true);
+087 }
+088
+089 public Listing3111()
+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 }
+
+ |
++Listing3111.java | +
+Die drei Dialoge, die durch Aufrufe von OKDialog, +YesNoDialog und YesNoCancelDialog +generiert werden, sind in den folgenden Abbildungen 31.16 +bis 31.18 dargestellt: +
+ +
+Abbildung 31.16: Ein Aufruf von OKDialog
++ +
+Abbildung 31.17: Ein Aufruf von YesNoDialog
++ +
+Abbildung 31.18: Ein Aufruf von YesNoCancelDialog
+| Titel + | Inhalt + | Suchen + | Index + | DOC + | Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 + |
| << + | < + | > + | >> + | API + | © 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de + |