Einführung in die AWT

Die Java-Programmiersprachenklassenbibliothek bietet ein Toolkit für die Benutzeroberfläche, das als Abstract Windowing Toolkit oder AWT bezeichnet wird. Das AWT ist sowohl leistungsstark als auch flexibel. Neuankömmlinge stellen jedoch häufig fest, dass ihre Macht verschleiert ist. Die Klassen- und Methodenbeschreibungen in der verteilten Dokumentation bieten dem neuen Programmierer nur wenige Anleitungen. Darüber hinaus lassen die verfügbaren Beispiele häufig viele wichtige Fragen offen. Natürlich sollten Neulinge mit einigen Schwierigkeiten rechnen. Effektive grafische Benutzeroberflächen sind von Natur aus schwierig zu entwerfen und zu implementieren, und die manchmal komplizierten Interaktionen zwischen Klassen in der AWT machen diese Aufgabe nur komplexer. Mit der richtigen Anleitung ist die Erstellung einer grafischen Benutzeroberfläche mit dem AWT jedoch nicht nur möglich, sondern auch relativ einfach.

Dieser Artikel behandelt einige der Philosophien hinter dem AWT und befasst sich mit der praktischen Frage, wie eine einfache Benutzeroberfläche für ein Applet oder eine Anwendung erstellt werden kann.

Was ist eine Benutzeroberfläche?

Die Benutzeroberfläche ist der Teil eines Programms, der mit dem Benutzer des Programms interagiert. Benutzeroberflächen haben viele Formen. Die Komplexität dieser Formulare reicht von einfachen Befehlszeilenschnittstellen bis hin zu grafischen Point-and-Click-Benutzeroberflächen, die von vielen modernen Anwendungen bereitgestellt werden.

Auf der untersten Ebene überträgt das Betriebssystem Informationen von der Maus und der Tastatur als Eingabe an das Programm und stellt Pixel für die Programmausgabe bereit. Das AWT wurde so konzipiert, dass sich Programmierer weder um die Details des Verfolgens der Maus oder des Lesens der Tastatur kümmern noch sich um die Details des Schreibens auf den Bildschirm kümmern müssen. Das AWT bietet eine gut gestaltete objektorientierte Schnittstelle zu diesen Diensten und Ressourcen auf niedriger Ebene.

Da die Java-Programmiersprache plattformunabhängig ist, muss die AWT auch plattformunabhängig sein. Das AWT wurde entwickelt, um eine Reihe allgemeiner Tools für das Design grafischer Benutzeroberflächen bereitzustellen, die auf einer Vielzahl von Plattformen funktionieren. Die vom AWT bereitgestellten Elemente der Benutzeroberfläche werden mithilfe des nativen GUI-Toolkits jeder Plattform implementiert, wodurch das Erscheinungsbild jeder Plattform erhalten bleibt. Dies ist eine der Stärken des AWT. Der Nachteil eines solchen Ansatzes ist die Tatsache, dass eine auf einer Plattform entworfene grafische Benutzeroberfläche anders aussehen kann, wenn sie auf einer anderen Plattform angezeigt wird.

Komponenten und Behälter

Eine grafische Benutzeroberfläche besteht aus grafischen Elementen, die als Komponenten bezeichnet werden. Typische Komponenten sind Elemente wie Schaltflächen, Bildlaufleisten und Textfelder. Mithilfe von Komponenten kann der Benutzer mit dem Programm interagieren und dem Benutzer visuelles Feedback zum Status des Programms geben. In der AWT sind alle Benutzeroberflächenkomponenten Instanzen der Klasse Component oder eines ihrer Subtypen.

Komponenten stehen nicht alleine da, sondern befinden sich in Containern. Container enthalten und steuern das Layout von Komponenten. Behälter sind selbst Bestandteile und können somit in anderen Behältern platziert werden. In der AWT sind alle Container Instanzen der Klasse Container oder eines ihrer Untertypen.

Räumlich müssen die Komponenten vollständig in den Behälter passen, in dem sie enthalten sind. Durch diese Verschachtelung von Komponenten (einschließlich Containern) in Containern wird ein Baum von Elementen erstellt, beginnend mit dem Container an der Wurzel des Baums und bis zu den Blättern, bei denen es sich um Komponenten wie Schaltflächen handelt.

Die Abbildung in Abbildung 1 zeigt eine einfache grafische Benutzeroberfläche, wie sie unter Windows 95 aussehen würde. Abbildung 2 zeigt die als Baum angeordneten Schnittstellenkomponenten aus Abbildung 1.

Arten von Komponenten

Abbildung 3 zeigt die Vererbungsbeziehung zwischen den vom AWT bereitgestellten Komponentenklassen der Benutzeroberfläche. Klassenkomponente definiert die Schnittstelle, an der alle Komponenten haften müssen.

Das AWT bietet neun grundlegende Nicht-Container-Komponentenklassen, aus denen eine Benutzeroberfläche erstellt werden kann. (Natürlich können neue Komponentenklassen von einer dieser Klassen oder von der Klassenkomponente selbst abgeleitet werden.) Diese neun Klassen sind Klassenschaltfläche, Leinwand, Kontrollkästchen, Auswahl, Beschriftung, Liste, Bildlaufleiste, TextArea und TextField. Abbildung 4 zeigt eine Instanz jeder Klasse.

Sie benötigen einen Java-fähigen Browser, um dieses Applet anzuzeigen.

Figur 4.

Neun Komponenten der Benutzeroberfläche

Die Quelle für diese Anzeige finden Sie hier.

Arten von Behältern

Das AWT bietet vier Containerklassen. Sie sind die Klasse Window und ihre beiden Untertypen - Klasse Frame und Klasse Dialog - sowie die Panel-Klasse. Zusätzlich zu den vom AWT bereitgestellten Containern ist die Applet-Klasse ein Container - sie ist ein Subtyp der Panel-Klasse und kann daher Komponenten enthalten. Nachfolgend finden Sie kurze Beschreibungen der einzelnen Containerklassen, die vom AWT bereitgestellt werden.

Fenster Eine Anzeigefläche der obersten Ebene (ein Fenster). Eine Instanz der Window-Klasse ist weder an einen anderen Container angehängt noch in diesen eingebettet. Eine Instanz der Window-Klasse hat keinen Rahmen und keinen Titel.
Rahmen Eine Anzeigefläche der obersten Ebene (ein Fenster) mit einem Rahmen und einem Titel. Eine Instanz der Frame-Klasse verfügt möglicherweise über eine Menüleiste. Es ist ansonsten einer Instanz der Window-Klasse sehr ähnlich.
Dialog Eine Anzeigefläche der obersten Ebene (ein Fenster) mit einem Rahmen und einem Titel. Eine Instanz der Dialog-Klasse kann ohne eine zugeordnete Instanz der Frame-Klasse nicht existieren.
Panel

Ein generischer Container zum Halten von Komponenten. Eine Instanz der Panel-Klasse stellt einen Container bereit, zu dem Komponenten hinzugefügt werden können.

Container erstellen

Vor dem Hinzufügen der Komponenten, aus denen eine Benutzeroberfläche besteht, muss der Programmierer einen Container erstellen. Beim Erstellen einer Anwendung muss der Programmierer zuerst eine Instanz der Klasse Window oder Class Frame erstellen. Beim Erstellen eines Applets ist bereits ein Frame (das Browserfenster) vorhanden. Da die Applet-Klasse ein Subtyp der Panel-Klasse ist, kann der Programmierer die Komponenten der Instanz der Applet-Klasse selbst hinzufügen.

Der Code in Listing 1 erstellt einen leeren Rahmen. Der Titel des Frames ("Beispiel 1") wird im Aufruf des Konstruktors festgelegt. Ein Frame ist zunächst unsichtbar und muss durch Aufrufen seiner show()Methode sichtbar gemacht werden .

import java.awt. *;

öffentliche Klasse Beispiel1 {public static void main (String [] args) {Frame f = neuer Frame ("Beispiel 1");

f.show (); }}

Listing 1:

Ein leerer Rahmen

Der Code in Listing 2 erweitert den Code aus Listing 1, sodass die neue Klasse von Class Panel erbt. In der main()Methode wird eine Instanz dieser neuen Klasse erstellt und über einen Aufruf der add()Methode zum Frame-Objekt hinzugefügt . Das Ergebnis wird dann angezeigt. Die Ergebnisse beider Beispiele sollten identisch aussehen (dh sie sollten ziemlich uninteressant aussehen).

import java.awt. *;

öffentliche Klasse Beispiel1a erweitert Panel {public static void main (String [] args) {Frame f = neuer Frame ("Beispiel 1a");

Beispiel1a ex = neu Beispiel1a ();

f.add ("Center", ex);

f.pack (); f.show (); }}

Listing 2:

Ein Rahmen mit einer leeren Tafel

Durch Ableiten der neuen Klasse vom Klassen-Applet anstelle des Klassen-Panels kann dieses Beispiel jetzt entweder als eigenständige Anwendung oder als in eine Webseite eingebettetes Applet ausgeführt werden. Der Code für dieses Beispiel ist in Listing 3 enthalten. Das resultierende Applet ist in Abbildung 5 dargestellt (und immer noch recht uninteressant).

import java.awt. *;

öffentliche Klasse Beispiel1b erweitert java.applet.Applet {public static void main (String [] args) {Frame f = neuer Frame ("Beispiel 1b");

Beispiel1b ex = neu Beispiel1b ();

f.add ("Center", ex);

f.pack (); f.show (); }}

Listing 3:

Ein Frame mit einem leeren Applet

Sie benötigen einen Java-fähigen Browser, um dieses Applet anzuzeigen.

Abbildung 5.

Ein leerer Rahmen

Hinweis: Ein Fensterobjekt und in bestimmten Fällen sogar ein Dialogobjekt können das Rahmenobjekt ersetzen. Sie sind alle gültige Container, und Komponenten werden auf dieselbe Weise zu jedem hinzugefügt.

Hinzufügen von Komponenten zu einem Container

Um nützlich zu sein, muss eine Benutzeroberfläche aus mehr als nur einem Container bestehen - sie muss Komponenten enthalten. Komponenten werden Containern über die add()Methode eines Containers hinzugefügt . Es gibt drei Grundformen der add()Methode. Die zu verwendende Methode hängt vom Layout-Manager des Containers ab (siehe Abschnitt Komponentenlayout ).

Der Code in Listing 4 fügt dem in Listing 3 dargestellten Code die Erstellung von zwei Schaltflächen hinzu. Die Erstellung erfolgt in der init()Methode, da sie während der Applet-Initialisierung automatisch aufgerufen wird. Unabhängig davon, wie das Programm gestartet wird, werden die Schaltflächen erstellt, da init()sie entweder vom Browser oder von der main()Methode aufgerufen werden . Abbildung 6 enthält das resultierende Applet.

import java.awt. *;

öffentliche Klasse Beispiel3 erweitert java.applet.Applet {public void init () {add (neuer Button ("One")); add (neuer Button ("Zwei")); }}

public Dimension PreferredSize () {neue Dimension zurückgeben (200, 100); }}

public static void main (String [] args) {Frame f = neuer Frame ("Beispiel 3");

Beispiel3 ex = neu Beispiel3 ();

ex.init ();

f.add ("Center", ex);

f.pack (); f.show (); }}

Listing 4:

Ein Applet mit zwei Tasten

Sie benötigen einen Java-fähigen Browser, um dieses Applet anzuzeigen.

Abbildung 6.

Ein Applet mit zwei Tasten

Komponentenlayout

Bis jetzt wurde nichts darüber gesagt, wie die Komponenten, die einem Container hinzugefügt wurden, angeordnet sind. Das Layout wird nicht vom Container gesteuert, sondern von einem dem Container zugeordneten Layout-Manager. Der Layout-Manager trifft alle Entscheidungen zur Platzierung der Komponenten. In der AWT implementieren alle Layout Manager-Klassen die LayoutManager-Schnittstelle.

Das AWT bietet fünf Layout-Manager. Sie reichen von sehr einfach bis sehr komplex. Dieser Artikel behandelt nur die beiden Layout-Manager-Klassen, die in den vorliegenden Beispielen verwendet werden: die FlowLayout-Klasse und die BorderLayout-Klasse.

Die FlowLayout-Klasse platziert Komponenten von links nach rechts in einem Container. Wenn der Platz in einer Zeile erschöpft ist, wird eine weitere Zeile gestartet. Die Einzelargumentversion der add()Methode eines Containers wird zum Hinzufügen von Komponenten verwendet.

Die BorderLayout-Klasse verfügt über fünf Zonen (siehe Abbildung 7). Die Zonen heißen "Nord", "Süd", "Ost", "West" und "Mitte". In jeder dieser fünf Zonen kann eine einzelne Komponente platziert werden. Wenn die Größe des umschließenden Containers geändert wird, wird die Größe jeder Randzone gerade so geändert, dass die darin platzierte Komponente aufgenommen werden kann. Jeglicher überschüssige Platz wird der mittleren Zone zugewiesen. Die Version der Containermethode mit zwei Argumenten add()wird zum Hinzufügen von Komponenten verwendet. Das erste Argument ist ein String-Objekt, das die Zone benennt, in der die Komponente platziert werden soll.

Jede Containerklasse verfügt über einen Standardlayoutmanager. Der Standard-Layout-Manager für die Frame-Klasse und die Dialog-Klasse ist der BorderLayout-Manager. Der Standard-Layout-Manager für die Panel-Klasse (und die Applet-Klasse) ist der FlowLayout-Manager.

Der Code in Listing 5 verwendet beide Layout-Manager und enthält einige weitere Komponenten der Benutzeroberfläche. Das Ergebnis ist in Abbildung 8 dargestellt.

import java.awt. *;

öffentliche Klasse Beispiel4 erweitert java.applet.Applet {public void init () {Panel p;

setLayout (neues BorderLayout ());

p = neues Panel ();

p.add (neues TextArea ());

add ("Center", p);

p = neues Panel ();

p.add (neuer Button ("Eins")); p.add (neuer Button ("Zwei"));

Auswahl c = neue Auswahl ();

c.addItem ("eins"); c.addItem ("zwei"); c.addItem ("drei");

p.add (c);

add ("Süd", p); }}

public static void main(String [] args) { Frame f = new Frame("Example 4");

Example4 ex = new Example4();

ex.init();

f.add("Center", ex);

f.pack(); f.show(); } }

Listing 5.

A more complicated example

You need a Java-enabled browser to view this applet.

Figure 8.

A more complicated example

Event handling

The examples above do nothing more than display an inert user interface. It is, of course, very important that a user interface take action as a result of user input. It is, however, beyond the scope this article to delve deeply into the mysteries of event handling. That must wait until a future article. However, in the interest of completeness, the example code in Listing 6 shows how to handle one type of event a program may receive. The new class overrides the action() method provided by the Component class. The action() method responds to the action events that are generated, for example, by the selection of an item from a pop-up list. The action() method requires that two parameters be supplied, an Event instance and an Object instance. The Event instance contains information about the event, including the target of the event (the component that first received the event), the x and y coordinates of the event, and the time when the event occurred. The Object instance holds an event-specific piece of data. For Button objects it contains the text in the button label.

import java.awt.*;

public class Example5 extends java.applet.Applet { TextArea ta = null;

public void init() { Panel p;

setLayout(new BorderLayout());

p = new Panel();

ta = new TextArea();

p.add(ta);

add("Center", p);

p = new Panel();

p.add(new Button("One")); p.add(new Button("Two"));

Choice c = new Choice();

c.addItem("one"); c.addItem("two"); c.addItem("three");

p.add(c);

add ("Süd", p); }}

öffentliche boolesche Aktion (Ereignis e, Objekt o) {String str = (String) o;

ta.appendText (str + "\ n");

falsch zurückgeben; }}

public static void main (String [] args) {Frame f = neuer Frame ("Beispiel 5");

Beispiel5 ex = neu Beispiel5 ();

ex.init ();

f.add ("Center", ex);

f.pack (); f.show (); }}

Listing 6:

Ein Beispiel für die Ereignisbehandlung