JAVA 3D – Seminar Wintersemester 2002/2003 Christian Schneider AWT – Detailbetrachtung Das Abstract Window Toolkit Fachhochschule Fulda – University of Applied Sciences Fachbereich Angewandte Informatik Marquardstraße 35, 36039 Fulda Postfach 2254, 36012 Fulda Inhalt 0 EINLEITUNG ................................................................................................................................... 1 1 EINFÜHRUNG INS AWT ................................................................................................................ 2 2 1.1 Was ist das AWT? ................................................................................................................... 2 1.2 Plattformunabhängigkeit.......................................................................................................... 2 1.3 Komponenten – Die Grundlage des AWT ............................................................................... 3 1.4 Klassendiagramme des AWT .................................................................................................. 4 DIE BAUSTEINE DER GRAFISCHEN BENUTZEROBERFLÄCHE DES AWT IM DETAIL ........ 6 2.1 2.1.1 Knöpfe (Button) ............................................................................................................. 7 2.1.2 Schalter (Checkbox)....................................................................................................... 8 2.1.3 Auswahlfelder (Choice)................................................................................................ 10 2.1.4 Listenfelder (List) ........................................................................................................ 11 2.1.5 Menüs (Menu, MenuItem etc.) .................................................................................. 12 2.1.6 Textmarken (Label) ..................................................................................................... 13 2.1.7 Textfelder (TextField)................................................................................................ 14 2.2 3 4 Die Basis-Bausteine ................................................................................................................ 6 Weitere Bausteine, um Benutzereingaben zu ermöglichen .................................................. 15 2.2.1 Textbereiche (TextArea) ............................................................................................. 15 2.2.2 Bildlaufleisten und Schiebebalken (Scrollbar).......................................................... 16 2.3 Containers: Windows, Panels und Scroll Panes ................................................................... 18 2.4 Canvas................................................................................................................................... 18 DAS EVENT-MODELL DES AWT ................................................................................................ 20 3.1 Event-Lauscher definieren..................................................................................................... 21 3.2 Lauscher für Quelle registrieren ............................................................................................ 22 3.3 Adapter .................................................................................................................................. 22 3.4 Eventverarbeitung durch Listener und Adapter..................................................................... 23 3.5 Ein einfaches Beispiel für Eventbehandlung ......................................................................... 24 GRAFIKAUSGABE....................................................................................................................... 25 4.1 Graphics-Klasse .................................................................................................................... 25 4.2 Methoden allgemein .............................................................................................................. 25 4.3 Zeichengebiete ...................................................................................................................... 26 4.3.1 Koordinatensystem........................................................................................................ 26 4.3.2 Clipping.......................................................................................................................... 26 4.4 Farbe ..................................................................................................................................... 27 4.5 Grafikfiguren .......................................................................................................................... 27 4.6 Übersicht über die Methoden der Graphics-Klasse............................................................... 28 5 LITERATUR- UND QUELLENANGABE ...................................................................................... 29 6 ANHANG ....................................................................................................................................... 29 Christian Schneider AWT - Detailbetrachtung 0 Einleitung Diese Arbeit entstand im Rahmen der Lehrveranstaltung „Java3D – Seminar“ bei Prof. Dr. Heinzel. Ziel der Ausarbeitung ist es, dem Teilnehmer der Veranstaltung eine Übersicht über die verschiedenen Möglichkeiten des AWT-Packages zu geben. AWT (Abstrakt Window Toolkit) ist die Grundlage aller Grafikanwendungen in Java, so dass der Programmierer dieses Package auf jeden Fall kennen sollte. Diese Einführung stellt nicht den Anspruch der absoluten Vollständigkeit, da es im zur Verfügung stehenden Zeitrahmen unmöglich wäre, alle Aspekte des AWT zu behandeln. Die folgende Ausarbeitung dient als Leitfaden durch die große Welt des AWT von Java. Es sei auch auf Fachliteratur verwiesen (s. Absatz 5. Literatur- und Quellenangabe). Christian Schneider 1 AWT - Detailbetrachtung 1 Einführung ins AWT 1.1 Was ist das AWT? Zur Entwicklung von Applets und grafischen Applikationen in Java™ benötigt man zu einem gewissen Grad das Abstract Window Toolkit, im Nachfolgenden AWT genannt. Es ist ein Teil des frei verfügbaren Java 2 SDK, des Java 2 Software Development Kits. Auch in den früheren Versionen der Java-Entwicklungsumgebungen, dem JDK (Java Development Kit) war das AWT bereits vorhanden. In den folgenden Ausführungen werden die alten JDK-1.0Standards nicht mehr berücksichtigt. Das AWT beinhaltet verschiedene Klassen, welche alle mit java.awt beginnen. Mit ihnen werden dem Programmierer hunderte von Klassen und Methoden zur Verfügung gestellt, aus denen er sich, einem Baukasten ähnlich, die gewünschte Oberfläche und Funktion holen kann. Es ist also nicht schwer, in einer Applikation oder einem Applet eine grafische Benutzeroberfläche zu nutzen, man muss „nur“ die richtige Klasse zur Hand nehmen und sie nach seinen Wünschen (um-)gestalten. 1.2 Plattformunabhängigkeit Das AWT ist eine der wichtigsten Klassenbibliotheken von Java, wenn nicht sogar die wichtigste. Es ist plattformunabhängig und stellt das GUI auf jeder Plattform etwas anders dar. Was ist das GUI? Unter GUI (Graphical User Interface) versteht man die grafische Benutzerschnittstelle einer Anwendung (Applikation oder Applet). Das AWT stellt eine GUI-Bibliothek dar und „vermittelt“ quasi zwischen dem Java-Programm und dem GUI des Betriebssystems. Das AWT wurde von Anfang an so entworfen, dass es ein plattformunabhängiges API (engl. application programming interface) haben und dennoch der Applikation das jeweilige betriebssystemspezifische Aussehen geben sollte. Zum Beispiel hat das AWT nur ein API für Knöpfe (in der Button-Klasse), aber es sieht auf einem Macintosh anders aus als auf einem PC, auf dem z.B. Windows XP läuft. Das AWT nutzt die Standardsteuerelemente der jeweiligen Plattform, was zur Folge hat, dass sich die Funktionalität der AWT-Komponenten an diesen Standardsteuerelementen orientiert. Für jedes Standardsteuerelement des Betriebssystems gibt es im AWT eine eigene Klasse. Die AWT-Komponenten setzten als so genannte „heavyweight“-Komponenten auf den betriebssystemspezifischen Implementierungen (auch „peers“ (auf deutsch „Gleiche“) genannt) auf. Java Java Native GUI Programm AWT (WinXP, etc.) Christian Schneider Display 2 AWT - Detailbetrachtung 1.3 Komponenten – Die Grundlage des AWT Ein Programm, das auf Fenster basiert, wird vom AWT als eine Hierarchie von ineinander verschachtelten Bausteinen angesehen, den so genannten Komponenten. Für jede Komponente gibt es im AWT eine eigene Klasse, von der der Programmierer entweder direkt eine Instanz bilden oder eigene Klassen ableiten kann. Man kann folgende wichtigen Gruppen von Klassen unterscheiden, je nach dem, welche Aufgabe den einzelnen Bausteinen beim Aufbau der grafischen Benutzeroberfläche zukommt: • Component: Das AWT ist eine Welt von Komponenten. Die java.awt.ComponentKlasse ist eine abstrakte Klasse für Komponenten wie Buttons, Labels, Lists usw. Die meisten Klassen im AWT sind Unterklassen der java.awt.Component-Klase. Auf ihr baut das AWT auf. Siehe Klassendiagramm unter 1.4. • Container ist eine abstrakte Klasse, die von Component erbt. Container sind Bausteine, die mehrere andere Komponenten enthalten (engl. contain) können. In ihnen werden die Oberflächenelemente gruppiert und die Oberfläche wird so strukturiert. Die wichtigsten Unterklassen von Container sind Panel, Applet, Window, Dialog und Frame. • LayoutManager ist ein Interface, das Methoden zur Positionierung und Größeneinteilung von Objekten innerhalb eines Containers definiert. Java™ definiert mehrere Standard-Layout-Manager. (Hierzu gibt es im Rahmen der Veranstaltung einen gesonderten Beitrag.) • Die Klasse Graphics ist die abstrakte Oberklasse aller Grafikkontexte, die Anwendungen ermöglichen, auf Komponenten usw. zu zeichnen. • Eine Komponente der Klasse Canvas (dt. Zeichenfläche) ist ein spezieller Baustein, der zum Malen und zur Anzeige von Bildern und Grafiken verwendet wird. Christian Schneider 3 AWT - Detailbetrachtung 1.4 Klassendiagramme des AWT Abbildung 1-1 Klassendiagramm - java.awt Christian Schneider 4 AWT - Detailbetrachtung Abbildung 1-2 Klassendiagramm - java.awt-components Wie in dem Klassendiagramm (aus Java™ API, Band 2, der offiziellen Dokumentation von JavaSoft) zu sehen ist, erben die meisten Komponenten der grafischen Benutzeroberfläche von der AWT Component-Klasse, mit Ausnahme der Menü-Komponenten. Aufgrund von Plattform übergreifenden Einschränkungen (z.B. die fehlende Möglichkeit, die Menü-Hintergrund-Farbe zu setzen) erben die Menü-Komponenten von der AWT-Klasse MenuComponent. Christian Schneider 5 AWT - Detailbetrachtung 2 Die Bausteine der grafischen Benutzeroberfläche des AWT im Detail 2.1 Die Basis-Bausteine Die Klassen (besser gesagt die Instanzen/Objekte der Klassen) Button, Checkbox, Choice, List, MenuItem und TextField stellen „klassische“ Kontrollmittel dar. Sie sind die am meisten genutzten Arten, einem Java-Programm Instruktionen zu geben. Wenn ein Benutzer einen dieser Bausteine aktiviert – z.B. durch Klicken eines Knopfes oder durch Drücken der Eingabetaste in einem Textfeld – dann erzeugt er ein sog. ActionEvent. Damit können mittels des entsprechenden Event-Listeners Befehle ausgeführt werden. Das Event-Modell von AWT wird später in Abschnitt 3 betrachtet. Das Label stellt eine Ausnahme dar. Es stellt lediglich eine nicht auswählbare Textzeile dar. Abbildung 2-1 Überblick über alle wichtigen AWT-Komponenten Christian Schneider 6 AWT - Detailbetrachtung 2.1.1 Knöpfe (Button) public class java.awt.Button extends java.awt.Component { // Konstruktoren public Button(); public Button(String label); // Methoden public void addNotify(); public String getLabel(); // Die Button-Klasse // erzeugt Knopf unbeschriftet // erzeugt Knopf mit Beschriftung // hier nicht betrachtet /* Rückgabe der Beschriftung oder null, wenn kein Label vorh.*/ protected String paramString(); /* Rückgabe des Zustands des Knopfes als Zeichenkette */ public void setLabel(String label); } Diese Klasse erzeugt eine beschriftete Schaltfläche (engl. labeled button), auch kurz Knopf genannt. Die Anwendung kann reagieren, wenn auf die Schaltfläche gedrückt wird. Nachfolgend sehen wir drei verschiedene Ansichten eines „Abbrechen“-Knopfes unter Windows: Abbildung 2-2 Knopfzustände Das erste Bild zeigt den Knopf im Normalzustand. In der zweiten Ansicht hat der Knopf den Eingabefokus, d.h. der dunkle Rand zeigt dem Benutzer, dass der Knopf aktiv ist. Und im dritten Fall wird gerade vom Benutzer auf den Knopf per Maus geklickt. So werden die damit verbundenen Aktionen ausgelöst. Wird ein Knopf gedrückt und danach wieder losgelassen, so sendet das AWT ein entsprechendes Ereignis (Event) an das Knopfobjekt1. Das EventHandling wird in Abschnitt 3 noch eingehender betrachtet. Im Folgenden ist das Bild eines (einfachen) Applets zu sehen, das drei Knöpfe zeigt. Abbildung 2-3 ButtonDemo – Applet //In der Initialisierung des Applets steht folgendes: public void init() { b1 = new Button(); b1.setLabel("Mittleren Knopf deaktivieren"); b2 = new Button("Mittleren Knopf"); b3 = new Button("Mittleren Knopf aktivieren"); b3.disable(); . . . 1 In Java 1.1 sendet das AWT alle Maus-, Tastatur und Fokusereignisse, die über dem Knopf auftreten. In Java 1.0 sendet das AWT keine Maus- oder Fokusereignisse. Christian Schneider 7 AWT - Detailbetrachtung Hier kann man gut sehen, wie ein Knopf angelegt wird. In der init()-Funktion des Applets, d.h. bei seiner Initialisierung, werden drei Instanzen der Klasse Button angelegt, nämlich b1, b2 und b3. Der Knopf b1 wird mittels des einfachen Konstruktors instanziiert, ohne ihm eine Beschriftung zu verpassen. Dies wird mit b1.setLabel("Mittleren Knopf deaktivieren"); nachgeholt. Den Knöpfen b2 und b3 werden mittels des Konstruktors Beschriftungen übergeben. „b3.disable();“ bedeutet, wie oben leicht zu sehen, dass der dritte Knopf zu Beginn des Applets deaktiviert wird, d.h. nicht der Benutzer kann ihn nicht anklicken. Nun müssen die Knöpfe nur noch dem Applet, welches ja auch einen Container darstellt, hinzugefügt werden. . . . // und hier werden die Knöpfe dem Applet (Container) hinzugefügt. add(b1); add(b2); add(b3); } 2.1.2 Schalter (Checkbox) Die Klasse Checkbox stellt Checkboxen oder auch Schalter zur Verfügung, die zwei Zustände annehmen können, entweder „ein“ oder „aus“. Diese Zustände werden durch eine boolsche Variable beschrieben (z.B.: boolean state). Ist der Schalter aktiviert, so sein Status „true“. Das folgende Bild zeigt ein (einfaches) Applet, das die Funktionsweise von Schaltern demonstriert: Abbildung 2-4 Checkbox-Demo Wie leicht auf dem Bild zu sehen ist, gibt es zwei „Arten“ von Schaltern. Auf der linken Seite sind voneinander unabhängige Schalter zu sehen, die alle entweder „ein“ oder „aus“ sein können. Die Schalter auf der rechten Seite sind in einer sog. CheckboxGroup angeordnet, also einer Gruppierung von Schaltern. Wenn Schalter zu einer Schaltergruppe gehören, kann immer nur einer dieser Schalter „ein“ (true) sein. Die Schaltergruppe CheckboxGroup ist eine selbständige Klasse. Christian Schneider 8 AWT - Detailbetrachtung Der folgende Code-Ausschnitt zeigt, wie in das Applet in Abbildung 2-4 die Schalter hinzugefügt werden: . . . Panel p1, p2; //Diesen Panels werden die Schalter hinzugefügt. Checkbox cb1, cb2, cb3; //Dies sind die unabhängigen Schalter. Checkbox cb4, cb5, cb6; //Diese Schalter gehören zu der Gruppe. CheckboxGroup cbg; //Checkboxgruppe cbg wird deklariert. cb1 = new Checkbox(); //Konstruktor. Default Status ist "aus" (false). cb1.setLabel("Checkbox 1"); //Schalter wird beschriftet. cb2 = new Checkbox("Checkbox 2"); //In der Klammer steht die Beschriftung. cb3 = new Checkbox("Checkbox 3"); cb3.setState(true); //Den Schalter auf “an” schalten (true). . . . cbg = new CheckboxGroup(); cb4 = new Checkbox("Checkbox 4", cbg, false); //Status: “aus” (false) cb5 = new Checkbox("Checkbox 5", cbg, false); // Status: “aus” cb6 = new Checkbox("Checkbox 6", cbg, true); // Status: “ein” (true) . . . /* cb4, cb5 und cb6 werden im Konstruktor bereits der CheckboxGroup cbg hinzugefügt.*/ p1 = new Panel(); p1.setLayout(new FlowLayout()); p1.add(cb1); // Schalter zu Panel 1 hinzufügen p1.add(cb2); // Schalter zu Panel 1 hinzufügen p1.add(cb3); // Schalter zu Panel 1 hinzufügen // usw... Für Checkboxen gibt es auch interessante Methoden, z.B. liefert public boolean getState() den Wert des Schalters, also seinen Zustand zurück. Angewendet auf den dritten Schalter (auf dem Bild unten links), würde cb3.getState() den Wert „true“ zurückgeben. Mit der Methode void setState(boolean state) kann man einem Schalter einen Zustand zuweisen, z.B. mit cb1.setState(true) würde man den Schalter links oben aktivieren. Mit setLabel(String s) kann man dem Schalter eine neue Beschriftung verpassen. Dann wird die Beschriftung mit dem Wert des Labels (Parameter in der Klammer der Methode) mit dem neuen String überschrieben. Mit getCheckboxGroup() erhält man als Rückgabewert die CheckboxGroup, in der sich der aufrufende Schalter befindet oder null, wenn er keiner Gruppe angehört. Mit setCheckboxGroup(CheckboxGroup g) kann man den Schalter in eine Gruppe hinzufügen, indem man ihn in dem Argument in der Klammer der Methode die entsprechende CheckboxGroup übergibt. Befindet er sich bereits in einer Gruppe, wird er aus dieser entfernt. Die CheckboxGroup überwacht den Status der in ihr enthaltenen Schalter. Christian Schneider 9 AWT - Detailbetrachtung 2.1.3 Auswahlfelder (Choice) Die Klasse Choice bietet ein aufblendbares Menü, das dem Benutzer Auswahlmöglichkeiten zur Verfügung stellt. Daher heißt die Klasse Choice oder Auswahlmenü (engl. choice menu). Die aktuelle Auswahl wird als Titel des Menüs angezeigt. Auswahlmenüs sind nützlich, um eine (große) Anzahl von Alternativen mit begrenztem Platz darzustellen, für den Fall, dass der Nutzer nicht alle Möglichkeiten gleichzeitig sehen muss. Ein anderer Name für Choices sind Pop-Up-Listen. Im Folgenden wird ein Beispiel eines (einfachen) Applets behandelt, das wie folgt aussieht, das volle Beispiel ist im Anhang enthalten. Abbildung 2-5 ChoiceDemo //...Hier werden Instanzen der Variablen definiert: Choice choice; //pop-up list of choices //...Hier wird initialisiert: choice = new Choice(); //neue Auswahl choice.addItem("ichi"); //neues Auswahlelement “ichi”, index = 0!!! choice.addItem("ni"); //neues Auswahlelement “ni” choice.addItem("san"); //neues Auswahlelement “san” choice.addItem("yon"); //neues Auswahlelement “yon” label = new Label(); //Text neben der Auswahl setLabelText(choice.getSelectedIndex(), choice.getSelectedItem()); //. . . usw... Es gibt noch weitere nützliche Methoden, die von der Klasse bereitgestellt werden: int countItems() String getItem(int) void select(int) void select(String) Christian Schneider Æ gibt die Anzahl der Elemente in der Auswahl zurück Æ gibt den String zurück, der an Position (int) der Auswahl steht !!!Zu beachten: Die Nr. des ersten Elements der Liste ist 0!!! Æ wählt das Element aus, das an Position (int) der Auswahl steht Æ wählt das Element aus, das den spezifizierten String anzeigt 10 AWT - Detailbetrachtung 2.1.4 Listenfelder (List) Die Komponente List stellt sich dem Anwender als eine verschiebbare Liste (engl. scrolling list) von Texteinträgen (engl. text items) dar. Die Liste kann so konfiguriert werden, dass der Benutzer nur einen oder mehrere Einträge auswählen kann. Das Anklicken eines noch nicht gewählten Eintrages wählt ihn aus (engl. select) Das Anklicken eines bereits ausgewählten Eintrages nimmt die Auswahl wieder zurück (engl. deselect). Ist bei der Erzeugung der Liste mittels des Konstruktors public List(int rows, boolean multipleSelections); das zweite Argument false, so kann maximal ein Eintrag der Liste ausgewählt werden. z.B.: List l = new List(4, false); //4 Eintr. sichtbar, ein Element auswählbar. Wird ein Element der Liste ausgewählt, so sendet das AWT der Liste ein LIST_SELECTEreignis. Gilt das Element als nicht ausgewählt, dann sendet das AWT der verschiebbaren Liste ein LIST_DESELECT-Ereignis. Wird ein Doppelklick auf dem Element ausgeführt (oder die Returntaste gedrückt), schickt das AWT dem LIST_SELECT- oder LIST_DESELECTEreignis ein ACTION_EVENT hinterher. Mit entsprechenden ActionListener und ItemListener können dann Events auf der Liste abgefangen werden und Anweisungen aufgerufen werden. List spanish = new List(4, true); spanish.addItem("uno"); spanish.addItem("dos"); spanish.addItem("tres"); spanish.addItem("cuatro"); spanish.addItem("cinco"); //usw. Abbildung 2-6 ListDemo Außer addItem(String item) (s.o.) gibt es noch weitere wichtige Methoden: public String getItem(int index) int countItems() void addItem(String, int) void replaceItem(String, int) void clear() void delItem(int) void delItems(int, int) Æ gibt den String der Liste an der angegebenen Position zurück Æ gibt die Anzahl der Elemente in der Liste zurück Æ fügt einen String an der angegebenen Position ein (index) Æ ersetzt den Eintrag an der angegebenen Position ein (index) Æ leert die Liste Æ löscht den Eintrag an der angegebenenPosition Æ löscht Einträge zwischen den angegebenen Positionen (inklusiv der „Ränder“) int getSelectedIndex() Æ gibt den Index des ausgewählten Elements zurück, -1, wenn nichts gewählt ist. int[] getSelectedIndexes() Æ gibt den Index der ausgewählten Elemente zurück String getSelectedItem() Æ wie getSelectedIndex(), liefert nur den String des Items String[] getSelectedItems() Æ vgl. getSelectedIndexes() void select(int), Æ Selektiert oder deselektiert das Element an der angegebenen void deselect(int) Position boolean isSelected(int) Æ liefert “true”, wenn das angegebene Item ausgewählt ist. int getRows() Æ liefert Anzahl der sichtbaren Zeilen boolean allowsMultipleSelections() Æ liefert “true”, wenn mehrfache Auswahl möglich ist boolean setMultipleSelections(true) Æ ermöglicht mehrfache Auswahl (bei true, bei false nicht) void makeVisible(int) Æ zwingt angegeben Eintrag, sichtbar zu sein int getVisibleIndex() Æ liefert Pos. des Eintrags, der zuletzt durch makeVisible() sichtbar gemacht wurde Christian Schneider 11 AWT - Detailbetrachtung 2.1.5 Menüs (Menu, MenuItem etc.) Menüs sind mit Auswahlfelder (Choice) vergleichbar, jedoch sind sie wesentlich umfassender. Im Gegensatz zu den bisher erklärten Komponenten erben Menüs ihre Funktionalität nicht von der Klasse Component, sondern von MenuComponent, weil einige Plattformen Menüs schwerwiegende Einschränkungen auferlegen. Im AWT stehen folgende Subklassen von MenuComponent zur Realisierung von Menüs zur Verfügung: • MenuItem zur Darstellung eines Menüeintrags • CheckboxMenuItem, denen eine Checkbox zugeordnet ist. So kann ein solches Menüelement ähnlich einer Checkbox ausgewählt werden. CheckboxMenuItem ist eine Subklasse von MenuItem. • Menu repräsentiert ein vollständiges Menü-Objekt und ist eine Subklasse der Klasse MenuItem, so dass Submenüs leicht erzeugt werden können, indem ein Menü einfach einem anderen hinzugefügt wird. • MenuBar repräsentiert die Zuweisung einer Gruppe von Menüs an ein Fenster. Für jede Menükomponente können Events abgefangen werden, es kann auf Klicks entsprechend reagiert werden. Dieses Event-Handling wird hier nicht weiter beachtet. EventHandling siehe Abschnitt 3 (Das Event-Modell des AWT). Im Folgenden wird ein Beispielprogramm wird die Verwendung eines Menüs demonstriert: Menu MenuBar MenuItem Abbildung 2-7 Menü Demo public class Menus extends Frame {// eigene Klasse Menus von Frame ableiten public Menus(String s) { // String s für Fenster Titel super(s); //Aufruf des Konstruktors der Oberklasse (für Titel) MenuBar mb; // Deklaration einer Menüleiste Menu m1, m2; // Deklaration der Menüs m1 und m2 MenuItem m1_1, m1_2,m2_1, m2_2; // Deklaration der Menükomponenten mb = new MenuBar();// Instanziierung der Menüleiste mb Christian Schneider 12 AWT - Detailbetrachtung setMenuBar(mb); // Aktivierung der Menüleiste im Fenster m1 = new Menu("Menü 1"); // Instanziierung des Menüs m1 mb.add(m1); // Hinzufügen des 1. Menüs zur Menüleiste m1_1 = new MenuItem("Menüeintrag 1_1"); // Instanziierung der Menükomponente m1_1 m1.add(m1_1); // Hinzufügen von m1_1 zum Menü 1 m1_2 = new MenuItem("Menüeintrag 1_2"); // usw. wie oben m1.add(m1_2); m2 = new Menu("Menü 2"); mb.add(m2); m2_1 = new MenuItem("Menüeintrag 2_1"); m2.add(m2_1); m2_2 = new MenuItem("Menüeintrag 2_2"); m2.add(m2_2); } ... 2.1.6 Textmarken (Label) Eine Textmarke (engl. label) ist eine Komponente, die einen Text in einem (beliebigen) Container platziert. Der Text kann von der Anwendung verändert werden, der Benutzer kann ihn jedoch nicht direkt editieren. Das Layout der Textmarke wird automatisch gesetzt. Zur Definition eines Labels können folgende Konstruktoren verwendet werden: • Label() erzeugt eine leere Textmarke, in der der Text linksbündig angeordnet wird. • Label(String) erzeugt eine Textmarke mit dem als Parameter übergebenen Text. Der Text wird ebenfalls linksbündig dargestellt. • Label(String, int) erzeugt die gleiche Ausgabe wie Label(String), nur legt der zweite Parameter die Ausrichtung des Textes innerhalb der Textmarke fest. Hierzu können die Integer-Konstanten (aus der Klasse Label) Label.LEFT, Label.CENTER und Label.RIGHT verwendet werden. Abbildung 2-8 Label Beispiel Das folgende Applet stellt ein Beispiel für die Verwendung von Textmarken dar, wie sie in Abbildung 2-8 zu sehen ist: import java.awt.*; import java.applet.*; public class Textmarke extends Applet { Label links = new Label("Label 1", Label.LEFT); // neue Textmarke Label zentriert = new Label("Label 2", Label.CENTER); // neue Textmarke Label rechts = new Label("Label 3", Label.RIGHT); // neue Textmarke Font f = new Font("Times", Font.BOLD, 20); public void init() { setFont(f); // Einstellen der Schriftart Times, Fett, Größe 20 add(links); // 1. Textmarke hinzufügen add(zentriert); // 2. Textmarke hinzufügen Christian Schneider 13 AWT - Detailbetrachtung } } 2.1.7 add(rechts); // 3. Textmarke hinzufügen Textfelder (TextField) Im Gegensatz zu Textmarken (s. 2.1.6) sind Textfelder vom Benutzer editierbar. Hierzu stellt Java die Klasse TextField zur Verfügung, deren Instanzen mit den folgenden Konstruktoren angelegt werden können: • TextField() erzeugt ein leeres Texteingabefeld ohne Größenangabe. • TextField(String) erzeugt ein Texteingabefeld, das mit dem als Parameter übergebenen Text gefüllt wird. Es erfolgt ebenfalls keine Größenangabe. • TextField(String, int) erzeugt ein Textfeld, wobei der Integer-Parameter die Breite des Feldes in der Anzahl der möglichen Buchstaben angibt. Es kann hier auch ein leerer String als String-Parameter übergeben werden. Die Klasse TextField stellt einige Methoden zur Verfügung, mit denen man die Textfelder kontrollieren kann: • getText() gibt den im Textfeld enthaltenen Text zurück, • setText(String) setzt diesen Text entsprechend, • isEditable() gibt einen booleschen Wert zurück, der angibt, ob das Textfeld editierbar ist (true) oder nicht (false), • setEditable(boolean) erlaubt (true) oder erlaubt nicht (false) das Editieren des Feldes. • setEchoChar(Char) ersetzt den eingegebenen Text durch das Zeichen Char. Abbildung 2-9 Textfeld-Demo Der folgende Code erzeugt ein Applet, das Textfelder demonstriert. Die Ausgabe ist in Abbildung 2-9 zu sehen. Christian Schneider 14 AWT - Detailbetrachtung import java.awt.*; import java.applet.*; public class Textfeld extends Applet { Label benutzerLabel = new Label("Benutzername"); TextField benutzerFeld = new TextField(50); // Textfeld Demo // Beschriftung // Textfeld erzeugen Label passwortLabel = new Label("Passwort"); TextField passwortFeld = new TextField(50); // Beschriftung // Textfeld erzeugen public void init() { add(benutzerLabel); add(benutzerFeld); add(passwortLabel); passwortFeld.setEchoChar('$'); add(passwortFeld); } hinzufügen hinzufügen hinzufügen als $ darstellen hinzufügen // // // // // Komponenten Komponenten Komponenten Textausgabe Komponenten } 2.2 Weitere Bausteine, um Benutzereingaben zu ermöglichen Sollten die unter 2.1 genannten Bausteine nicht geeignet oder ausreichend sein, kann man auch noch die Klassen Scrollbar (engl. für Bildlaufleiste) und TextArea (engl. für Textflächen) nutzen. Die Scrollbar-Klasse kann sowohl als Bildlaufleiste als auch als Schiebebalken (zum Regeln z.B.) genutzt werden. Bildlaufleisten sind automatisch integriert in Listen und Textflächen sowie in sog. Scrollfeldern (ScrollPane, s. 2.3). 2.2.1 Textbereiche (TextArea) Mittels der Klasse TextArea können mehrzeilige Textbereiche erzeugt werden, die größere Textmengen aufnehmen können als Textfelder. In einem Textbereich stehen horizontale und vertikale Schiebebalken zur Verfügung, mit denen man den gewünschten Anzeigebereich sichtbar machen kann. Folgende Konstruktoren dienen zur Erzeugung von Textbereichen: • TextArea() erzeugt einen leeren Textbereich ohne Angabe der Höhe und Breite. • TextArea() erzeugt einen Textbereich mit Angabe der Höhe und Breite. Der erste Parameter gibt die Anzahl der Zeilen und der zweite die Anzahl der Zeichen pro Zeile an. • TextArea(String) erzeugt einen Textbereich mit einem festgelegtem Text (String), aber ohne Angabe der Höhe und Breite. • TextArea(String, int, int) erzeugt den gleichen Textbereich wie TextArea(String) nur mit Größenangabe. Die Klasse TextArea stellt einige Methoden zur Verfügung, mit denen man die Textbereiche kontrollieren kann: Christian Schneider 15 AWT - Detailbetrachtung • getText(), setText(String), isEditable() und setEditable(boolean) analog zu Textfeldern (2.1.7) • insert(String, int) fügt den Text, der durch den ersten Parameter angegeben wird, an der Indexposition in das Feld ein, die durch den zweiten Parameter angegeben wird (gemessen in Zeichen). • replace(String, int, int) ersetzt den Text zwischen den Positionen, die durch den zweiten und dritten Parameter bestimmt werden, durch den als erstes Argument übergebenen String. Das folgende Beispiel zeigt die Handhabung eines Textbereichs: Abbildung 2-10 Textbereich Demo import java.awt.*; import java.applet.*; public class Textbereich extends Applet { // Textbereich Demo String inhalt = "Mittels der Klasse TextArea können mehrzeilige " +"Textbereiche erzeugt werden,\ndie größere Textmengen aufnehmen können " +"als Textfelder.\nIn einem Textbereich stehen horizontale und vertikale " +"Schiebebalken zur Verfügung,\nmit denen man den gewünschten " +"Anzeigebereich sichtbar machen kann."; // Text für den Inhalt TextArea textFeld; // Deklaration von textFeld public void init() { textFeld = new TextArea(inhalt, 3, 20); // Instanz von textFeld add(textFeld); // textFeld hinzufügen } } 2.2.2 Bildlaufleisten und Schiebebalken (Scrollbar) Mittels der Scrollbar-Komponenten kann man einen Wert in der Form auswählen, dass man einen Schiebebalken (auch Slider genannt) horizontal oder vertikal verschiebt. Die jeweilige Position des Schiebebalkens repräsentiert dann den Wert einer Variablen. Beim Generieren des Schiebebalkens werden in der Regel der minimale und der maximale Wert angegeben, welche die Auswahl begrenzen. Es stehen folgende Konstruktoren zur Verfügung: • Scrollbar() erzeugt eine vertikale Scrollbar, bei der sowohl Minimum, als auch Maximum 0 sind. Christian Schneider 16 AWT - Detailbetrachtung • Scrollbar(int) erzeugt genau wie Scrollbar()eine Scrollbar, bei der sowohl Minimum, als auch Maximum 0 sind, wobei der Parameter die Orientierung des Schiebebalkens angibt. Man kann hier die in der Klasse Scrollbar enthaltenen Integer-Konstanten Scrollbar.VERTICAL und Scrollbar.HORIZONTAL verwenden. • Scrollbar(int, int, int, int, int) erzeugt eine Scrollbar mit folgenden Parametern: Orientierung (Scrollbar.VERTICAL oder Scroll- bar.HORIZONTAL), Anfangswert des Schiebebalkens, Breite und Höhe der Box, die zur Veränderung der Scrollbar verwendet wird, und der minimale und maximale Wert, zwischen denen die Scrollbar selektiert. Abbildung 2-11 Scrollbars Das folgende Beispiel zeigt die Verwendung der Klasse Scrollbar. Die Ausgabe ist in Abbildung 2-11 dargestellt. import java.awt.*; import java.applet.*; public class Scroll extends Applet { Scrollbar sbar0 = new Scrollbar(Scrollbar.HORIZONTAL, 0, 10, 10, 200); Scrollbar sbar1 = new Scrollbar(Scrollbar.VERTICAL, 100, 10, 10, 200); public void init() { add(sbar0); add(sbar1); } } Christian Schneider 17 AWT - Detailbetrachtung 2.3 Containers: Windows, Panels und Scroll Panes Das AWT stellt drei Typen von Containern zur Verfügung, die alle als Unterklassen der Container-Klasse implementiert sind (welche wiederum eine Unterklasse von Component ist). Die von der Klasse Window abgeleiteten Klassen Dialog, FileDialog und Frame stellen Fensterfunktionalitäten bereit, die Komponenten aufnehmen können. Frames erzeugen vollständige Fenster mit allen Eigenschaften, die wir es z.B. von Windows her kennen. Im Gegensatz dazu erzeugen Dialogs Fenster, die von Frames abhängen und die modal sein können (d.h. dass z.B. einige Fensterkomponenten nicht vorhanden sind, wie z.B. „Maximieren“, je nach Initialisierung). Nutzt man einen FileDialog, so erzeugt das Programm einen Dialog zum öffnen oder speichern von Dateien. (Bekannt aus diversen Anwendungen, z.B. unter Menüpunkt „öffnen“ oder „speichern unter“ usw.) Ein Panel gruppiert Komponenten im Bereich eines bereits bestehenden Fensters. Ein ScrollPane ist einem Panel sehr ähnlich, aber sein Zweck ist etwas anders. In einem ScrollPane werden (mitunter sehr große) Komponenten dargestellt, wenn nur ein beschränkter Raum zur Verfügung steht. Ist der Platz zu klein für das dargestellte Objekt, so kann man mittels Bildlaufleisten im ScrollPane scrollen, um sich den gewünschten Ausschnitt anzeigen zu lassen. 2.4 Canvas Eine Canvas-Komponente (dt. Zeichenfläche, s. auch Abbildung 2-1) ist eine rechteckige Fläche des Bildschirms, in die die Anwendung zeichnen kann oder darin auftretende Eingabeereignisse des Benutzers abfangen kann. Um eine sinnvolle (d.h. nicht leere) Ausgabe auf dem Bildschirm zu erreichen, muss der Programmierer eine Unterklasse von Canvas bilden. Dabei muss er die paint-Methode der Klasse überschreiben, damit eine beliebige Zeichnung, z.B. ein Dreieck, in die Zeichenfläche gesetzt werden kann. Das AWT sendet der Zeichenfläche alle Maus-, Tastatur- und Fokusereignisse, die über ihr auftreten. Die Methoden gotFocus, lostFocus, keyDown, keyUp, mouseEnter, mouseExit, mouseMove, mouseDrag, mouseDown und mouseUp der übergeordneten Klasse Component können überschrieben werden, um auf etwaige Ereignisse, die der Benutzer hervorruft, reagieren zu können. Christian Schneider 18 AWT - Detailbetrachtung Nun folgt ein Code-Beispiel (Auszug) für eine Canvas, welche den Code für die Canvas aus dem Fenster in Abbildung 2-1 darstellt. class MeineCanvas extends Canvas { ... ... } // Eigene Klasse von Canvas ableiten public void paint(Graphics g) { // paint(...)-Methode überschreiben int w = getSize().width; // Integer-Wert für die Breite int h = getSize().height; // Integer-Wert für die Höhe g.drawRect(0, 0, w - 1, h - 1);// Canvas einen "Rahmen" geben g.drawString("Canvas", (w g.getFontMetrics().stringWidth("Canvas"))/2,10); } g.drawLine(10,10, 100,100); // Linie zeichnen g.fillRect(9,9,3,3); // Rechteck zeichnen g.drawString("(10,10)", 13, 10);// Beschriftung zeichnen g.fillRect(49,49,3,3); // Rechteck zeichnen g.drawString("(50,50)", 53, 50);// Beschriftung zeichnen g.fillRect(99,99,3,3); // Rechteck zeichnen g.drawString("(100,100)", 103, 100); //usw. Die Methode public void paint(Graphics g) wird aufgerufen, um den Inhalt der Zeichenfläche erneut zu zeichnen. Der Punkt <0,0> des Graphikkontexts ist die obere linke Ecke der Zeichenfläche. Zum Koordinaten-System innerhalb der Canvas bzw. des AWT allgemein wird noch in Abschnitt 4 (Grafikausgabe) Stellung genommen. Christian Schneider 19 AWT - Detailbetrachtung 3 Das Event-Modell des AWT Jede Benutzeraktion (z.B. Mausklick, Mausbewegung oder Tastaturanschlag) veranlasst das im Hintergrund laufende Windowing-System (z.B. Windows XP) dazu, ein der Aktion entsprechendes Ereignis (engl. Event) zu erzeugen. Dieses wird an das Programm weitergeleitet, das gerade den Fokus hatte, d.h. in dessen Fensterbereich das Event ausgelöst worden ist. Nun kommt das AWT ins Spiel, es verwendet zur Behandlung von Events ein sog. Delegation Event Modell. ActionListener MouseListener KeyListener Quelle Lauscher mit der der Anwender interagiert der Ereignis bearbeitet Abbildung 3-1 Event-Quelle und Event-Lauscher In dem Event-Modell wird zwischen Event-Quelle (event source) und Event-Lauscher (event listener) unterschieden. Die Quellen sind die Komponenten der GUI, z.B. ein Knopf oder ein Fenster. Die Event-Lauscher sind Klassen, die zum Abfangen und Behandeln der Events erzeugt werden. Will man ein Ereignis über einer bestimmten Komponente abfangen, so muss man einen passenden Event-Listener definieren und diesen für die betreffende Quelle mit entsprechenden Methoden registrieren. Der erste Schritt zur Ereignisbehandlung besteht darin, das Package java.awt.event zu importieren. In diesem sind einige Klassen und Interfaces zusammengefasst, die für die Ereignisbehandlung benötigt werden. Prinzipiell ist das Ziel der Ereignisbehandlung, dass das Programm immer entsprechend reagiert, wenn der Benutzer z.B. auf einen Schalter drückt. Daher müssen für jede Komponente Methoden definiert werden, die immer dann aufgerufen werden, wenn das zugehörige Ereignis über der Komponente eintritt. Christian Schneider 20 AWT - Detailbetrachtung 3.1 Event-Lauscher definieren Lauscher sind Klassen, die bestimmte Listener-Interfaces implementieren. In den Interfaces werden die Methoden deklariert, die dann beim Eintreten des Events ausgeführt werden sollen. Für jede Art von Ereignissen (Maus-, Tastatur-, Fensterereignisse) gibt es eigene Listener-Interfaces (s. Tabelle 3-1). Der Programmierer muss nun eigene Klassen definieren, die diese Interfaces implementieren. Die beispielhafte Syntax zur Definition einer eigenen Klasse, die das „einfachste“ Listener-Interface, den ActionListener, implementiert, sieht so aus: class MeinActionLauscher implements ActionListener { // Definiton der Methoden des Interface } Das Interface ActionListener deklariert eine einzige Methode: public abstract void actionPerformed(ActionEvent e) Da die in den Interfaces deklarierten Methoden abstrakt sind, müssen sie noch definiert werden, damit das Ereignis eine „Wirkung“ hervorruft. Ohne eine passende Implementierung dieser Methoden ist eine Ereignisbehandlung nicht möglich. Eine beispielhafte Implementierung der Methode actionPerformed aus dem kleinen Beispiel sieht wie folgt aus: class MeinActionLauscher implements ActionListener { public void actionPerformed(ActionEvent e) { // das Ereignis ruft ein einmaliges Piepen hervor java.awt.Toolkit.getDefaultToolkit().beep(); } } Man kann an diesem kleinen Beispiel mehrere interessante Punkte feststellen: • actionPerformed ist die Methode, die später beim entsprechenden Ereignis (z.B. Button drücken) aufgerufen wird. • Die Signatur der Methode wird vom Interface vorgegeben, implementiert wird sie vom Programmierer erst in der eigenen Klasse. D.h. die Methode im Interface ist abstrakt und wird erst definiert, wenn der Programmierer das Interface nutzen will. • Die Methode definiert einen Parameter e, dem zur Laufzeit vom Betriebssystem eine Instanz der Klasse ActionEvent übergeben wird. In dieser Instanz sind alle wichtigen Informationen zum auslösenden Event enthalten. Christian Schneider 21 AWT - Detailbetrachtung 3.2 Lauscher für Quelle registrieren Wenn nun ein Lauscher und eine Quelle vorhanden sind, müssen diese nur noch adäquat zusammengeführt werden. Man spricht davon, dass man einen Listener für eine Quelle registriert. Die Komponenten, also die Quellen, definieren hierfür passende add...Listener()-Methoden, für jedes der verschiedenen Listener-Interfaces eine. Zum Beispiel wird nun die entsprechende Methode für einen Knopf (button) aufgerufen, um ihm eine Instanz der oben exemplarisch definierten Lauscher-Klasse zu übergeben: MeinActionLauscher abc = new MeinActionLauscher(); // Lauscher-Instanz button.addActionListener(abc); // Lauscher beim Knopf registrieren Man kann bei einer Komponente jede Art von Lauscher-Objekten registrieren. Die verschiedenen Lauscher sind in Tabelle 3-1 dargestellt. 3.3 Adapter Da die in den Interfaces deklarierten Methoden abstrakt sind, müssen sie immer implementiert werden. In dem kleinen Beispiel mit dem ActionListener musste nur eine Methode definiert werden, actionPerformed. Es gibt jedoch weitere Interfaces (s. Tabelle 3-1), die mehrere Methoden deklarieren. Z.B. deklariert der WindowListener sieben Ereignisbehandlungsmethoden. Da der Benutzer aber alle Methoden definieren muss (da sie abstrakt sind), sind manche Interfaces ziemlich „unhandlich“. Um den Zwang zu umgehen, alle Methoden der Interfaces einzeln definieren zu müssen, kann der Programmierer auf sog. AdapterKlassen zurückgreifen. Diese Adapter-Klassen sehen eine Implementierung aller Methoden eines Listener-Interfaces ohne Anweisungen vor. Also sind alle Methoden eines Interfaces in der dazugehörigen Adapter-Klasse bereits definiert, so dass der Programmierer sie nicht explizit definieren muss. Wenn er eine Adapter-Klasse verwendet, kann er alle Methoden neu definieren, muss es aber nicht. Wenn nur eine Methode gebraucht wird (z.B. windowClosing), dann muss nur diese neu definiert werden. Um dies an einem Beispiel zu verdeutlichen, wird nun das Interface WindowListener betrachtet. Es deklariert sieben Ereignisbehandlungsmethoden: windowOpend(), windowClosing(), windowClosed(), windowActivated(), windowDeactivated(), windowIconfied(), windowDeiconfied() Wenn man seine Lauscher-Klasse selbst erstellt, welche das Interface WindowListener implementiert, dann muss man alle sieben Ereignisbehandlungsmethoden definieren, egal, ob sie gebraucht werden oder nicht. Leitet man aber stattdessen seinen Lauscher von der Adapter-Klasse WindowAdapter ab, dann ist es lediglich notwendig, die benötigten Methoden zu überschreiben. Alle anderen Methoden können ignoriert werden. Christian Schneider 22 AWT - Detailbetrachtung Ein Beispiel für eine selbst erstellte Lauscher-Klasse, die von der Klasse WindowAdapter abgeleitet wird: class MeinWindowLauscher extends WindowAdapter { public void windowClosing(WindowEvent e) { // Das Programm beenden System.exit(0); } } In diesem Beispiel wird nur eine Methode der insgesamt sieben Methoden des WindowListene-Interfaces benötigt, so dass der Programmierer auf die zugehörige Adapter-Klasse zurückgegriffen hat, um sich so eine Definition der anderen sechs Methoden zu ersparen. 3.4 Eventverarbeitung durch Listener und Adapter Eine Übersicht über die verschiedenen Event-Arten gibt folgende Tabelle: Listener-Interface ActionListener AdjustmentListener ComponentListener ContainerListener FocusListener ItemListener Funktion Erfassung allgemeiner Aktionen Erfassung von Größenänderungen von Komponenten Erfassung von Komponentenaktionen Erfassung von Containeraktionen Erfassung von Fokusänderungen Erfassung von Zustandsänderungen Adapterklasse Methoden keine actionPerformed keine adjustmentValueChanged ComponentAdapter ContainerAdapter FocusAdapter keine KeyListener Erfassung von Tastaturaktionen KeyAdapter MouseListener Erfassung von Mausaktionen MouseAdapter MouseMotionListener TextListener WindowListener Erfassung von Mausbewegungen Erfassung von Textänderungen Erfassung von Fensteraktionen MouseMotionAdapter componentHidden componentMoved componendResized componendShown componentAdded componentRemoved focusGained focusLost itemStateChanged keyPressed keyReleased keyTyped mouseClicked mouseEntered mouseExited mousePressed mouseReleased mouseDragged mouseMoved keine textValueChanged WindowAdapter windowOpend windowClosing windowClosed windowActivated windowDeactivated windowIconfied windowDeiconfied Tabelle 3-1 Event-Verarbeitung Christian Schneider 23 AWT - Detailbetrachtung 3.5 Ein einfaches Beispiel für Eventbehandlung Hier nun ein einfaches Beispiel für Eventbehandlung. Es zeigt drei Knöpfe, die jeweils unterschiedlich auf Klicks durch den Benutzer reagieren. Der mittlere Knopf erzeugt ein Piepen, der linke Knopf deaktiviert den mittleren Knopf und der rechte Knopf aktiviert den mittleren Knopf. In den Kommentaren sind Hinweise zur Funktionsweise des Applets: Abbildung 3-2 ButtonDemo import import import import java.awt.*; java.awt.event.ActionListener; java.awt.event.ActionEvent; java.applet.Applet; public class ButtonDemo Button b1, b2, static final String static final String static final String // Import der benötigten Klassen extends Applet // Eigene Klasse ButtonDemo implements ActionListener { b3; DISABLE = "disable"; ENABLE = "enable"; BEEP = "beep"; // // // // Knöpfe String String String werden deklariert Konstanten werden definiert Konstanten werden definiert Konstanten werden definiert public void init() { // Initialisierung des Applets b1 = new Button(); // neuer Knopf b1 wird angelegt b1.setLabel("BEEP Knopf deaktivieren"); // b1 wird beschriftet b1.setActionCommand(DISABLE); // bei Event "sendet" der Knopf // "disable" b2 = new Button("BEEP"); // neuer Knopf b2 wird angelegt b2.setActionCommand(BEEP); // bei einem Event "sendet" der Knopf // "beep" b3 = new Button("BEEP Knopf aktivieren");// neuer Knopf b3 b3.setEnabled(false); // Knopf wird deaktiviert b3.setActionCommand(ENABLE); // bei Event "sendet" der Knopf // "ENABLE" b1.addActionListener(this); // Lauscher für b1 registrieren b2.addActionListener(this); // Lauscher für b2 registrieren b3.addActionListener(this); // Lauscher für b3 registrieren add(b1); // b1 zum Applet hinzufügen add(b2); // b2 zum Applet hinzufügen add(b3); // b3 zum Applet hinzufügen } } public void actionPerformed(ActionEvent e) {// Definition der Methode String command = e.getActionCommand(); //Welches Event ist passiert? if (command.equals(DISABLE)) { // "BEEP Knopf deaktivieren" geklickt b2.setEnabled(false); // b2 deaktivieren b1.setEnabled(false); // b1 deaktivieren b3.setEnabled(true); // b3 aktivieren } else if (command.equals(ENABLE)) {//"BEEP Knopf aktivieren" geklickt b2.setEnabled(true); // b2 aktivieren b1.setEnabled(true); // b1 aktivieren b3.setEnabled(false); // b3 deaktivieren } else // Beep!!! java.awt.Toolkit.getDefaultToolkit().beep(); } Christian Schneider 24 AWT - Detailbetrachtung 4 Grafikausgabe Da nicht nur Komponenten (also Knöpfe, Schiebebalken etc.) beim Design von grafischen Benutzeroberflächen von Bedeutung sind, wird im Folgenden die Grafikausgabe mittels AWT betrachtet. Das Hauptaugenmerk liegt hierbei bei der Klasse Graphics. Mit dieser stehen unterschiedlichste Funktionen zur Verfügung, z.B. zum Zeichnen von Figuren oder die Ausgabe von Text. 4.1 Graphics-Klasse Im AWT stehen durch die Graphics-Klasse viele Grafikmöglichkeiten zur Verfügung. Mit ihr können Linien, Formen, Text und Bilder auf dem Bildschirm ausgegeben werden. Die Graphics-Klasse ist Teil des java.awt-Packages und wird mit der import Anweisung (import java.awt.* oder import java.awt.Graphics) am Anfang der Quelldatei importiert. Die Klasse Graphics ist die abstrakte Oberklasse aller Grafikkontexte, die es ermöglicht auf prinzipiell allen Oberflächen zu zeichnen, d.h auf den Komponenten oder nicht dargestellten Bildern (engl. off-screen images). Falls nichts anderes angegeben wird, ändern die mit einem Grafikobjekt durchgeführten Grafikoperationen nur die Bits, die innerhalb des Ausschnittbereichs (engl. clipping area) des Grafikkontextes liegen. Alles Zeichnen und Schreiben erfolgt in der aktuellen Farbe, dem aktuellen Zeichenmodus (engl. paint mode) und in der aktuellen Schrift. 4.2 Methoden allgemein Grafikmethoden sind Methoden innerhalb der Graphics-Klasse, welche meistens innerhalb der paint-Methode des Applets, der Komponente oder einer Zeichenfläche (Canvas, s. 2.4) ausgeführt werden. Auf die verschiedensten Zeichnungsfunktionen wird unter 4.5 noch eingegangen. Beispiel: Eine Linie zwischen den Koordinaten x1=30, y1=20 und x2=80, y2=100: public void paint(Graphics g) { g.drawLine(30,20,80,100); } Der paint-Methode wird hier ein Graphics-Objekt übergeben. Es ist nicht nötig, eine Instanz dieses Objektes zu erzeugen, es steht vielmehr innerhalb von paint automatisch zur Verfügung. Die folgende Abbildung 4-1 zeigt das Ergebnis dieser Grafikoperation: Christian Schneider 25 AWT - Detailbetrachtung X (0,0) Bereich, in dem gezeichnet wird. (30,20) drawLine(30,20,80,100) (80,100) (width-1, height-1) Y Abbildung 4-1 Zeichnen einer Linie und Koordinatensystem 4.3 Zeichengebiete 4.3.1 Koordinatensystem Wie in Abbildung 4-1 angedeutet ist, hat eine jede Komponente ein eigenes Koordinatensystem, das von (0,0) bis (width-1, height-1) reicht. Jede Einheit entspricht einer Pixelgröße. Im Normalfall ist, wie in der Abbildung, der Ursprung, d.h. (0,0), in der oberen linken Ecke zu finden. Die x-Werte wachsen zunehmend nach rechts, die y-Werte nach unten. Mit der Funktion translate(int x, int y) kann man den Ursprung aber auch umsetzen. 4.3.2 Clipping Man kann das Zeichengebiet auch durch das sog. Clipping verkleinern. clipRect(int x, int y, int width, int height) Grafikoperationen außerhalb des so festgelegten Bereichs haben keine Auswirkung. Zum Beispiel erlaubt g.clipRect(70, 50, 260, 100); das Zeichnen nur in einem Bereich, der 260 Pixel breit und 100 Pixel hoch ist. Die linke obere Ecke dieses Bereiches ist durch x=70, y=50 festgelegt. Christian Schneider 26 AWT - Detailbetrachtung 4.4 Farbe Farben sind in Java eigene Objekte und es gibt eine Vielzahl von Methoden, um sie zu benutzen oder ändern. Zum Beispiel setzt die Anweisung setBackground(Color.black) die Hintergrundfarbe einer Komponente auf Schwarz. Color.black ist dabei eine statische Klassenvariable, die die Farbe Schwarz definiert. Die meisten Grundfarben sind auf diese Weise direkt verfügbar (Color.green, Color.blue usw.). Natürlich kann auch jede beliebige andere Farbe erzeugt werden, z.B. mit g.setColor(new Color(255,255,0). Dies erzeugt die Farbe Gelb nach dem RGBSystem. Auf dieses wird hier aber nicht explizit eingegangen. 4.5 Grafikfiguren Grafikfiguren im AWT sind Linien, Rechtecke, Rechtecke mit runden Ecken, 3D-Rundecke, Ovale, Kreisbögen und Polygone. Abbildung 4-2 Grafikfiguren mit Methoden In der Abbildung 4-2 sieht man den Satz von Grund-Zeichenfunktionen, den die die Graphics-Klasse zur Verfügung stellt. Die einzelne Implementierung der jeweiligen Methoden und deren Handhabung sollte man in der Java API und der Online-Dokumentation von Sun nachschlagen, eine ausgiebige Behandlung würde nun zu weit führen. Auch in der Methoden-Übersicht unter 4.6 erhält man Informationen zu den gängigsten Funktionen. Christian Schneider 27 AWT - Detailbetrachtung 4.6 Übersicht über die Methoden der Graphics-Klasse Hier die wichtigsten Methoden der Graphics-Klasse in der Übersicht: Methode Beschreibung clearRect(int, int, int, int) Füllt einen spezifizierten Bereich mit der Hintergrundfarbe drawArc(int, int, int, int, int, int) Zeichnet einen Bogen ein drawImage(Image, int, int, ImageObserver) Zeichnet ein Bild an die angegebene Position drawLine(int, int, int, int) Zeichnet eine Linie ein drawOval(int, int, int, int) Zeichnet ein Oval ein drawPolygon(int[], int[], int) Zeichnet ein Polygon ein drawPolyline(int[], int[], int) Zeichnet einen Linienzug ein drawRect(int, int, int, int) Zeichnet ein Rechteck ein drawRoundRect(int, int, int, int, int, int) Zeichnet ein Rechteck mit abgerundeten Ecken ein drawString(String, int, int) Gibt String an der angegebenen Koordinate aus fillArc(), fillOval(), fillPolygon()... getClip() Eine Reihe von Methoden zum Zeichnen ausgefüllter Formen (vgl. draw...()) Liefert ein Shape-Objekt zurück, das den aktuellen Clip-Bereich repräsentiert getColor() Liefert die aktuelle Zeichenfarbe zurück getFont() Liefert die aktuell verwendete Schriftart zurück setClip(Shape) Definiert einen neuen Clipping-Bereich setColor(Color) Definiert die beim Zeichnen verwendete Farbe setFont(Font) Definiert die zu verwendende Schriftart translate(int, int) Verschiebung des Nullpunktes Tabelle 4-1 Überblick über die Methoden der Graphics-Klasse Christian Schneider 28 AWT - Detailbetrachtung Literatur- und Quellenangabe 5 Als Informationsquellen wurden für diese Ausarbeitung verwendet: 6 • Open Java, Fischer/El Saddik, Springer-Verlag • Java – Programmierung interaktiver WWW-Seiten, Doberenz/Druckenmüller, Hanser-Verlag • JavaTM API – Band 2: Das Window Toolkit und Applets, Die offizielle Dokumentation von JavaSoft Gosling/Yellin/Java-Team, Addison-Wesley-Verlag • graphic Java – Mastering the AWT 2nd edition Geary • http://sun.java.com Java-Online-Dokumentation von Sun • Jetzt lerne ich Java Dirk Louis / Peter Müller, Verlag Markt und Technik Anhang Im Anhang befindet sich eine CD mit Dateien und Quelltexten zu den meisten Beispielen. Es wurde darauf verzichtet, diese alle auszudrucken. Außerdem sind auf der CD ausführbare Beispiel-Applets, die den Sachverhalt deutlich machen sollen. Man kann sie durch öffnen der jeweiligen HTML-Files betrachten. Wenn dieses Dokument von CD geöffnet wurde, dann kann man durch anklicken der Links (s.u.) zu den Beispielen gelangen. Die folgenden Hyperlinks führen zu den Beispielen (auf CD): ButtonDemo.html ButtonDemo.java Demo zu Knöpfen und Ereignisbehandlung FontDemo.html FontDemo.java Demo der verschiedenen Grafikformen GUIWindow.html GUIWindow.java Demo der verschiedenen Komponenten des AWT Scrollbar.html Scroll.java Demo für einen Scrollbalken Textfeld.html Textfeld.java Demo für Textfelder Textbereich.html Textbereich.java Demo für Textbereiche Textmarke.html Textmarke.java Demo für Textmarken (Label) Christian Schneider 29