| Titel | Inhalt | Suchen | Index | API | Go To Java 2, Zweite Auflage, Handbuch der Java-Programmierung |
| << | < | > | >> | Kapitel 31 - GUI-Dialoge | |
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:
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("Center", new Label(msg));
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("South", panel);
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("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 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 | API | Go To Java 2, Zweite Auflage, Addison Wesley, Version 2.0 |
| << | < | > | >> | © 2000 Guido Krüger, http://www.gkrueger.com | |