Java-Tipp 48: So erstellen Sie eine wiederverwendbare MessageBox-Klasse

Als Programmierer und Berater stelle ich häufig Fragen (häufig in Newsgroups) wie: "Warum wird mein modales Dialogfeld immer gesperrt?", "Wie extrahiere ich, auf welche Schaltfläche der Benutzer in meinem OKCancelDialogfeld geklickt hat ?" und "Warum hat Java keine Standard-MessageBox?" In diesem Java-Tipp habe ich eine Lösung bereitgestellt, die all diese Fragen berücksichtigt. Was ist diese umfassende Antwort? Eine wiederverwendbare MessageBoxKlasse (für Java 1.1 oder neuere Versionen), mit der Sie eine Nachricht und anklickbare Schaltflächen in einem Browserfenster anzeigen und eine Antwort vom Benutzer erhalten können. Es kommt in Form einer JavaBean.

Das bloße Minimum

Betrachten wir, was wir aus Sicht des Anwendungsfalls wollen . Ein Anwendungsfall besteht aus einer Reihe von Schritten, die ein Akteur ausführt, um ein Ziel zu erreichen. Wenn wir unsere Analystenhüte aufsetzen, wäre es schön, wenn wir eine MessageBoxKlasse hätten, in der wir einem Benutzer eine Frage stellen und eine Antwort erhalten könnten, beispielsweise wie folgt:

MessageBox box = new MessageBox (this); box.setTitle ("Bestätigung löschen"); box.addChoice ("Ja", "DeleteConfirmYes"); box.addChoice ("No", "DeleteConfirmNo"); box.addChoice ("Hilfe", "DeleteConfirmHelp"); box.setCloseWindowCommand ("DeleteConfirmNo"); box.ask ("Möchten Sie diesen Kunden wirklich löschen?");

Der obige Code ist ein Anwendungsfall auf der niedrigstmöglichen Ebene. Beachten Sie, dass wir das MessageBoxfür eine Vielzahl von Verwendungszwecken konfigurieren können - nicht nur für eine begrenzte, die die Antworten "Ja", "Nein" oder "Abbrechen" liefert. Es ist ein häufiger Anfängerfehler, einen zu erstellen MessageBox, der nur wenige Tastenkombinationen verarbeitet. Sobald Sie jedoch die Konfigurierbarkeit verstehen, wie in diesem einfachen Beispiel gezeigt MessageBox, sind Sie auf dem Weg, wiederverwendbare Klassen zu entwerfen.

Um eine Benachrichtigung zu erhalten, dass auf eine Schaltfläche geklickt wurde, müssen wir ActionListenerden Aktionsbefehl in implementieren und testen public void actionPerformed(Action evt).

Funktionen hinzufügen

Um MessageBoxeine erstklassige wiederverwendbare Klasse zu sein, benötigen wir einige weitere Funktionen. Was ist zum Beispiel, wenn wir ein haben Frameund ein modales Dialogfeld mit verwenden MessageBox? Sollten wir nicht MessageBoxmit unserem versorgen , damit der Fokus auf das zurückkehrt Frame, wenn das MessageBoxweg ist Frame? Was wir hinzufügen müssen, ist die folgende optionale Anwendungsfallfunktion:

box.setFrame (myFrame); 

Wie können wir unsere GUIs verbessern MessageBoxund dem Benutzer eine konzeptionellere Benutzerfreundlichkeit bieten, da die GUIs im Web immer besser werden ? Eine Möglichkeit, dies zu erreichen, besteht darin, zuzulassen, dass ein Bild zusammen mit der Nachricht angezeigt wird. Dazu müssen wir eine zusätzliche optionale Anwendungsfallfunktion hinzufügen:

box.useImageCanvas (lightBulbImage); 

Dies bedeutet jedoch, dass der Client das Image erstellen muss und häufig nur ein Standard-Image im selben Verzeichnis wie verwenden möchte MessageBox. In diesem Fall möchten wir eine einfachere Methode:

box.useImageCanvas ("LightBulb.gif"); 

Was ist, wenn wir häufig MessageBoxFragen verwenden, die Ja- und Nein-Antworten erfordern, und so Antwortfelder mit "Ja" und "Nein" erstellen? Was ist, wenn wir noch häufiger Fragen stellen, die am besten mit "Okay" beantwortet werden? In diesem Fall wären die nützlicheren Funktionen:

box.askYesNo ("Ist Java jetzt das defacto 3GL für intelligente Entwickler?"); 

und:

box.askOkay ("James Gosling, komm her, ich brauche dich."); 

Zusätzliche Anforderungen sind:

  • Der Dialog sollte den Thread, der ihn aufgerufen hat, nicht blockieren (siehe unten für einen Abschnitt darüber, was Deadlocking ist).

  • Das Fenster sollte sich selbst schließen, wenn auf eine Schaltfläche geklickt wird

  • Der Dialog sollte sich zum leichteren Lesen auf dem Bildschirm zentrieren

  • Der Dialog sollte modal sein , unabhängig davon , ob a Framebereitgestellt wird oder nicht . Mit modal meinen wir, dass Benutzer nur in das MessageBoxFenster klicken können , nirgendwo anders in der Anwendung

Schließlich, worauf Sie gewartet haben: MessageBoxCode

Jetzt, wo wir unsere Anforderungen gesenkt haben, können wir das Fabelhafte enthüllen MessageBox.

Untersuchen Sie den Quellcode MessageBoxin einem separaten Fenster. Da diese Codeliste zu lang ist, um in diesen Tipp aufgenommen zu werden, werden nur die Code-Highlights untersucht. MessageBoxverwendet eine andere wiederverwendbare Klasse: ImageCanvas. Beachten Sie die Klassendeklaration:

öffentliche Klasse MessageBox implementiert Runnable, ActionListener, WindowListener, KeyListener {und die wichtigste Methode: public void ask (String message) {if (frame == null) {frame = new Frame (); frameNotProvided = true; } else {frameNotProvided = false; } dialog = neuer Dialog (Rahmen, wahr); // Modal dialog.addWindowListener (this); dialog.addKeyListener (this); dialog.setTitle (title); dialog.setLayout (neues BorderLayout (5, 5)); Panel messagePanel = createMultiLinePanel (Nachricht); if (imageCanvas == null) {dialog.add ("Center", messagePanel); } else {Panel centerPanel = neues Panel (); centerPanel.add (imageCanvas); centerPanel.add (messagePanel); dialog.add ("Center", centerPanel); } dialog.add ("Süd", buttonPanel); dialog.pack (); erzwingenMinimumSize (Dialog, 200, 100); centerWindow (Dialog); Toolkit.getDefaultToolkit (). Beep ();// Starten Sie einen neuen Thread, um den Dialog anzuzeigen. Thread thread = new Thread (this); thread.start (); }}

Wir implementieren die Listener, um diese Ereignisse zu empfangen, und implementieren, Runnabledamit wir einen feinen und dandy Java-Thread erstellen können. Lassen Sie uns die verwandten Methoden untersuchen:

public void run () {dialog.setVisible (true); }}

Einfacher geht es nicht, oder? Beachten Sie ask(), dass wir einen neuen Thread starten, der zum Aufrufen führt run(), und dies zeigt den Dialog. Auf diese Weise vermeiden wir Deadlocks , die wir nun für einige Websekunden pausieren, um sie zu diskutieren.

Deadlock: Eine Definition

Der gesamte Java-Code wird in einem Thread oder in Threads ausgeführt. Wenn Sie beispielsweise ein Java-Programm durch Aufrufen von a starten main(), erstellt die Java-Laufzeit einen Thread und ruft main()innerhalb dieses Threads auf. In der Regel main()instanziiert die Methode eine Einstiegspunktklasse, die das System initialisiert und dem Benutzer ein Frameoder präsentiert Dialog. Der anfängliche Thread stirbt ab, wenn die main()Methode beendet ist. Der Grund, warum die Java-Laufzeit selbst nicht endet, ist, dass die AWT einen oder mehrere Benutzer-Threads erzeugt hat, um das AWT-Verhalten zu verwalten, einschließlich Benutzereingaben über Schaltflächen und dergleichen.

Wenn der Benutzer auf eine Schaltfläche klickt, sendet der zugrunde liegende "AWT-Thread" eine ActionEventan die Schaltflächen, ActionListenerdie über die Methode verfügen actionPerformed(ActionEvent evt). Angenommen actionPerformed(), Sie öffnen ein modales Dialogfeld, um den Benutzer etwas zu fragen. Wenn das modale Dialogfeld auf dem Bildschirm angezeigt wird, wird der Code blockiert . ("Blöcke" bedeutet, dass ein Thread auf die Benachrichtigung wartet, was im Fall eines modalen Dialogfelds erst dann geschieht, wenn das Fenster geschlossen wird.) Dies bedeutet, dass der aufgerufene AWT-Thread auf actionPerformed()die Rückkehr der Methode wartet . Dieser AWT-Thread kann jetzt keine Benutzereingaben mehr verarbeiten, z. B. in dem gerade geöffneten Dialogfeld. Ihre Anwendung ist also blockiert. Shucks.

Um diese Deadlock-Katastrophe zu vermeiden, wechseln Sie entweder zu einer "besseren" Sprache oder verwenden Sie die erweiterten Funktionen von Java (wodurch Java zur besseren Sprache wird). Zeigen Sie einfach das modale Dialogfeld in einem neuen Thread, und in Javaland sind alles Pfirsiche und Rosen. Dies haben wir im obigen Code getan. Diese Art von Deadlock ist häufig, bis man seine Ursache versteht und eine einfache Lösung hat, um dies zu verhindern.

Fazit

Der Rest MessageBoxist selbsterklärend. Studieren Sie den MessageBoxCode und die MessageBoxTestAnwendung und haben Sie Spaß.

JavaWorld möchte Ihren Java-Tipp an den Rest der Java-Welt weitergeben. Schreiben Sie jetzt Ihre coolsten Tipps und Tricks auf und senden Sie sie an [email protected] . Möglicherweise finden Sie sich in JavaWorld als Autor mit Ihren hilfreichen Hinweisen, die als nächster Java-Tipp ausgewählt wurden!

Jack Harich, auch bekannt als "Happy Jack", ist ein lebenslustiger Renaissance-Mann, der nach seiner Karriere als Bildhauer aufgrund einer Nackenverletzung schnell auf Software umstieg. Derzeit ist er Berater in Atlanta (dem Silicon Cotton Field des Südens) und sehr aktiv in der Atlanta Java User's Group, der Java As A Second Language SIG und dem Atlanta Java Consortium.

Erfahren Sie mehr über dieses Thema

  • Laden Sie hier alle notwendigen Dateien für das oben beschriebene Programm herunter

    //images.techhive.com/downloads/idge/imported/article/jvw/1998/03/javatip48.zip

Diese Geschichte "Java-Tipp 48: Erstellen einer wiederverwendbaren MessageBox-Klasse" wurde ursprünglich von JavaWorld veröffentlicht.