Ereignisse, MVC, AWT Ereignisse ■ Merkmale eines ereignisgesteuerten Programms That's That'sone onesmall smallstep step for foraaman, man,aagiant giantleap leap for mankind for mankind ■ Aufbau eines ereignisgesteuerten Programms ■ Entwicklung eines ereignisgesteuertes Programms in Java ■ Allgemeines zur Benutzerschnittstelle, MVC ■ Unterteilung in Model, View und Controller ■ Graphische Komponenten des AWT School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege Sequentielle Programme Beispiele sequentieller Programme ■ Hauptprogramm steuert den gesamten Programmablauf: in Java schreibt man dafür sog. Applikationen: die main Methode ist dort die Einsprungstelle (später) ■ Compiler, Batch-Processing, Scripts, Kommandozeilenbefehle (cd, dir, more), 2 von 62 public class App { static foo() {... } ■ Applets ohne graphische Benützeroberfläche (Methode paint ist dort Einsprungstelle) public static void main(String args) { foo(); } } ■ Programmablauf wird beim Programmieren festgelegt ■ Hauptprogramm ruft Unterprogramm(e) auf. ■ Diese geben am Ende jeweils die Kontrolle wieder an das Hauptprogramm zurück. Æ weniger geeignet für wirklich interaktive Programme ■ Verlangt an bestimmten Stellen Benutzereingaben ■ Zeitlicher Ablauf des Programms ist vor dem Start festgelegt ■ User kann nur an den vorbestimmten Stellen auf den Programmablauf Einfluss nehmen, nämlich dort, wo das Programm eine Eingabe verlangt School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 3 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 4 von 62 Ereignisgesteuertes Programm Ereignisgesteuerte Programme ■ Interaktive Anwendungen werden in Java mit ereignisgesteuerten Programmen (event-driven programs) geschrieben ■ Hauptmerkmal: Programmablauf ist nicht fix vorgegeben, sondern wird durch externe Ereignisse (events) gesteuert: ■ ■ ■ ■ Für die Benutzerschnittstelle wird von Java eine graphische Oberfläche zur Verfügung gestellt Æ GUI Graphical User Interface (AWT, JFC) School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege ■ Ereignis(endlos)schleife Methoden im UserProgramm Mausklick Menuauswahl Tastendruck Betriebssystem, andere Programme Ereignisschleife (event loop) ■ Das Hauptprogramm besteht aus einer Ereignisschleife ■ Diese wartet auf Ereignisse und läuft bis zum Abbruch des Programms kontinuierlich ■ Der Programmierer schreibt für jedes Ereignis eine entsprechende Methode ■ Beim Eintreffen eines Ereignisses ruft die Ereignisschleife die entsprechende Methode auf, um das eingetroffene Ereignis zu behandeln 5 von 62 School of Engineering Java Event Model ■ Java Laufzeitsystem (AWT) implementiert eine Ereignisschleife bereits Ereignisquelle (Source Object), z.B. Button ■ Der Programmierer muss nur noch die Methoden schreiben, die die Ereignisse behandeln ■ Definiert Ereignisse, die es erzeugen kann ■ Benutzer drückt auf Taste oder klickt mit der Maus Benutzer klickt eine Schaltfläche, eine Menuoption usw. an ■ Die Java GUI Komponenten (z.B. Button) bereiten diese Elementarereignisse auf ■ ■ Sie erzeugen daraus Java Ereignisse ■ © A. Meier/M. Braschler/J. Zeman/K. Rege Methode2 Methode2 Maustaste Maustaste betätigt? betätigt? Methode3 Methode3 ….? ….? Methode4 Methode4 ….? ….? : : 6 von 62 7 von 62 bietet Methoden zum An- und Abmelden von Listener an. z.B. addActionListener ■ Informiert Listener-Objekte, sobald ein Ereignis eingetreten ist: ■ Sie nehmen Elementarereignisse, die sie betreffen, entgegen School of Engineering Maus Maus bewegt? bewegt? ■ Führt eine Liste der Ereignissenken (Listener-Objekte), z.B. Applet ■ Die Ereignisschleife verarbeitet zusammen mit dem Betriebssystem die Elementarereignisse des Systems ■ Methode1 Methode1 © A. Meier/M. Braschler/J. Zeman/K. Rege Ereignisschleife und Events in Java ■ Taste Taste gedrückt? gedrückt? Das Source-Objekt ruft die entsprechende Methode beim Listener-Objekt auf Alle Informationen über das Ereignis (z.B. wer ist der Verursacher) werden dabei in einem Ereignis-Objekt übergeben School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 8 von 62 …Java Event Model Beispiel Interface Interface->->Klasse Klasseenthält enthält Methode MethodeaddActionListener addActionListener Listener, z.B. Applet import java.applet.*; ■ Registriert sich beim Source-Objekt als Listener public class DrueckMich extends Applet implements ActionListener { private Button tester; private boolean gedrueckt = false; @Override public void init() { tester = new Button("Hier drücken"); // GUI-Obj. erzeugen add (tester); // zur GUI hinzufügen tester.addActionListener(this); // Listener registrieren } Sich selber anmelden an Knopf, Bearbeitungsmethode Sich selber anmelden an Knopf, Bearbeitungsmethode dass an ActionEvents interessiert dass an ActionEvents interessiert public void actionPerformed(ActionEvent event) { gedrueckt = true; repaint(); } Ereignis Ereignis ■ Gibt damit an, an welchen Ereignissen es interessiert ist (Bsp. ActionEvent). ■ Stellt je eine Methode zur Behandlung der entsprechenden Ereignisse bereit ■ Interface bestimmt die Behandlungsmethode, z.B.ActionListener SourceObj.addActionListener(ListenerObj) Delegation-Event-Modell ■ Auftretende Ereignisse werden nicht zentral behandelt @Override public void paint(Graphics g) { if(gedrueckt) { g.drawString ("Danke!", 100,50); } } ■ Behandlung jedes Ereignisses wird vielmehr an ein oder mehrere Objekte delegiert School of Engineering import java.awt.*; import java.awt.event.*; © A. Meier/M. Braschler/J. Zeman/K. Rege } 9 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 10 von 62 Initialisierung Anmeldung: z.B. addActionListener Methode init() ■ Vordefinierte Methode der Klasse Applet Æ Wird ein einziges Mal bei der Initialisierung des Applet aufgerufen ■ In dieser Methode werden normalerweise alle benötigten Komponenten erzeugt und initialisiert ■ Allgemein sieht die Erzeugung eines Buttons folgendermassen aus: tester = new Button("Hier drücken"); ■ Dem Button tester wird ein Objekt als Listener für ActionEvents zugeordnet. Methode add() ■ Vordefinierte Methode der Klasse Applet © A. Meier/M. Braschler/J. Zeman/K. Rege ■ ■ Mit this wird hier das aktuelles Objekt (Applet) beim Button tester als Listener registriert; Æ d.h. die Methode für die Ereignisbehandlung (actionPerformed) befindet sich in diesem Applet !! Man hätte aber auch andere Objekte im Programm mit der Ereignissbehandlung "beauftragen" können. ■ Die Registrierungsmethoden für Listener-Objekte folgen einer einheitlichen Namensgebung. Ein Listener für ein Ereignis XXX hat den Namen ■ Fügt den Button zur graphischen Benutzeroberfläche hinzu ■ Man könnte hier auch schreiben add(tester); School of Engineering tester.addActionListener(this); SourceObjekt.addXXXListener(Listener-Obj.); 11 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 12 von 62 Bearbeitung bei Ereignis: z.B. actionPerformed Ereignisklassen: z.B. ActionEvent ■ Die Methode actionPerformed(ActionEvent e) wird vom Button tester ■ Es gibt zahlreiche Ereignisse, welche von Komponenten erzeugt werden können und an denen andere Objekte interessiert sind (Komponente = GUI-Objekte) jedesmal bei allen registrierten Listeners aufgerufen, wenn der Button gedrückt wird ■ In dieser Methode stehen die Anweisungen, die dieses Ereignis behandeln ■ Dieselbe Ereignisklasse wird von mehreren Komponenten verwendet. Z.B. ActionEvent ■ Wenn die Betätigung des Buttons eine Veränderung der GUI zur Folge hat (im Bsp.: drawString…), dann muss das Applet muss neu gezeichnet werden, um dem Benutzer die Reaktion des Programms anzuzeigen: Æ verwendet von Button, TextField,... repaint() fordert den Browser auf, das Applet neu zu zeichnen ■ Der Browser ruft sodann unter anderem die Methode paint() des Applets auf School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 13 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege Mehrere Buttons ActionEvent Object … Mehrere Buttons ActionEvent Object Mehrere Buttons … Mehrere Buttons public void init { smaller= new Button("smaller"); // add (smaller); // smaller.addActionListener(this);// bigger= new Button("bigger"); // add (bigger); // bigger.addActionListener(this); // } 14 von 62 ■ Mit der Methode e.getSource() kann das Source-Objekt abgefragt werden GUI-Obj. erzeugen zur GUI addieren Listener registrieren GUI-Obj. erzeugen zur GUI addieren Listener registrieren ■ Problem: Alle Buttons erzeugen ein Ereignis der gleichen Klasse ActionEvent und es wird die gleiche Methode ActionPerfomed aufgerufen . ■ Wie kann man herausfinden, welcher Button das Ereignis erzeugt hat? public void actionPerformed(ActionEvent event) { if (event.getSource() == smaller){ diameter -= 10; Referenzvergleich Referenzvergleich } if (event.getSource() == larger){ diameter += 10; } repaint(); } ■ Lösung: Das an die Methode actionPerformed(ActionEvent e) übergebene Ereignis-Objekt e enthält verschiedene Informationen zum Ereignis: z.B. Quelle des Ereignisses School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 15 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 16 von 62 Direkte Verarbeitung von Events in Applet ■ Bearbeitung des Ereignisses in Applet: ■ ■ Einfach ausreichend für einfache Aufgaben addXXListner(this) addXXListner(this) Entwurf von interaktiven Anwendungen Model, View, Controller ■ Nachteile: School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 17 von 62 ■ Verarbeitung ans Applet gebunden -> bei Wechsel auf andere GUI Klassenbibliothek neu programmieren ■ Vermischung von Darstellungslogik und Verarbeitungslogik -> Übersichtlichkeit leidet ■ Nicht möglich gleiches Ereignis durch mehrere GUI Elemente auszulösen School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 18 von 62 MVC: Beispiel Auto Trennung GUI und Verarbeitung ■ Wichtiges Entwurfsprinzip: Trennung und Entkopplung von Benutzerschnittstelle und „technischen Innereien“ (Verarbeitung, Modell) Controller Controller ■ Beispiel: Automobil ■ ■ View View Benutzerschnittstelle: Gaspedal, Kupplungspedal, Ganghebel, Steuerrad, Tachometer, Tourenzähler, Benzinanzeige... Technische Innereien: Motor, Getriebe, Kupplung, Lenkung, ABS, Lichtanlage ■ Vorteile: ■ ■ ■ Einfache und sichere Bedienung und Überwachung durch User Verstecken der Komplexität vor dem User Getrennte und damit einfachere Entwicklung und Wartung der Teilsysteme Model Model ■ Man unterscheidet 3 Teile: Model, View und Controller School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 19 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 20 von 62 Aufgabenteilung nach dem MVC Paradigma Vereinfachte Implementierung ■ Bearbeitung/Daten von Darstellung und Auslösen der Verarbeitung trennen ■ Controller und View sind meist miteinander gekoppelt bzw. in einer Klasse implementiert ■ ■ verschiedene Eingaben (Buttons, etc.) verschiedene Darstellungen (gleichzeitig) ■ ■ Controller delegiert Verarbeitung nur wird deshalb meist nicht als separaten Klasse implementiert ■ Klare Aufgabenteilung (Separation of Concerns) BenutzerereignisVerarbeitung Darstellung Controller Controller 1) initiiert Änderung der Daten View 1) initiiert Änderung der Daten 2) benachrichtigt über Datenänderung Viewer 2) benachrichtigt über Datenänderung 3) liest neue Daten und stellt diese dar Model 3) liest neue Daten und stellt diese dar Model Datenbehälter, inkl. Veränderungsmethoden School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 21 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege Beispiel Einfache View ■ Ein veränderbarer Kreis mit Methoden grow und shrink import java.awt.*; import java.awt.event.*; import java.applet.*;import java.beans.*; ■ View-Controller als Applet implementiert public class Applet1 extends Applet implements ActionListener, PropertyChangeListener { CircleModel model; Button grow; View-Controller Modelle Modellehaben haben oft oftProperties Properties ==Werte Werte public void init() { grow = new Button("Grow"); grow.addActionListener(this); add(grow); model = new CircleModel(50); model.addPropertyChangeListener(this); } public void actionPerformed(ActionEvent ev) { model.grow(); } CircleModel int value grow() shrink() 22 von 62 public void paint(Graphics g) { int r = model.getValue(); g.drawOval(100-r,100-r,2*r,2*r); } Model Controller View public void propertyChange(PropertyChangeEvent ev) { repaint(); } } School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 23 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 24 von 62 1) Initiieren der Datenänderung Controller 1) initiiert Änderung der Daten 2) Benachrichtigung über Datenänderungen Controller Viewer 2) benachrichtigt über Datenänderung Viewer 1) initiiert Änderung der Daten 3) liest neue Daten und stellt diese dar 2) benachrichtigt über Datenänderung 3) liest neue Daten und stellt diese dar Model Model Ereignismechanismus verwenden: PropertyChangedEvent ■ der Controller ruft die entsprechende Methode vom Model auf ■ 2a) View meldet sich beim Model an, dass an Ereignissen interessiert: public void actionPerformed(ActionEvent ev) { model.grow(); // nur noch Methodenaufruf } ■ addPropertyChangeListener(this) ■ einmalig, bei der Initialisierung ■ 2b) Ereignisbearbeiter-Methode ■ propertyChange School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 25 von 62 3) Lesen der Daten und Darstellung Controller 1) initiiert Änderung der Daten © A. Meier/M. Braschler/J. Zeman/K. Rege 26 von 62 Verschiedene Ereignisquelle Viewer 2) benachrichtigt über Datenänderung School of Engineering ■ Graphisches Element als Ereignisquelle ■ Button, etc Benutzereingabe 3) liest neue Daten und stellt diese dar Delegiere Verarbeitung Ereignis (Event) Ereignisquelle Model erzeuge Ereignis Objekt, z.B ActionEvent Ereignisverarbeiter verarbeitet z.B. in Methode actionPerformed ■ Lesen der Daten via Getter-Methode von Model ■ model.getValue() ■ Model als Ereignisquelle ■ Zustandsänderung als Ereignis ■ Anzeigen Zustandsänderung ■ repaint() aufrufen Ereignisquelle (Model) Ereignis (Event) Ereignisverarbeiter (View) erzeuge Ereignis Objekt School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 27 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 28 von 62 1) CircleModel Klasse grow() Methode 2a) Anmelden von View an CircleModel ■ Verwaltung von PropertyChangeListeners mit Klasse PropertyChangeSupport import java.awt.event.*; import java.beans.*; import java.awt.event.*; public class CircleModel { private int value; public class CircleModel{ private int value; private PropertyChangeSupport props; public CircleModel(int value) { this.value = value; } public CircleModel(int value) { this.value = value; props = new PropertyChangeSupport(this); } public void setValue(int val) { value = val; } Anmeldemethode, dass an PropertyChangeEvents interessiert public void grow() { setValue(value+1); } Methode um Werte zu ändern public void addPropertyChangeListener(PropertyChangeListener list) { props.addPropertyChangeListener(list); } } } School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 29 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 2b) Benachrichtigung von View bei Änderung 3) Auslesen von Wert ■ Methode setValue anpassen, dass PropertyChangeEvent bei Änderung ■ Auslesen des Werts mittels getValue-Methode 30 von 62 ausgelöst wird; public class CircleModel { ……… firePropertyChange(String name, Object oldVal, Object newVal); import java.beans.*; import java.awt.event.*; public int getValue() { return value; } public class CircleModel { } …… public void setValue(int val) { old = value); value = val; props.firePropertyChange("value",old,val); } …… } School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 31 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 32 von 62 CircleModel komplett Zusammenfassung: MVC import java.beans.*; import java.awt.event.*; ■ Model: der Datenbehälter ■ View: zur Darstellung der Daten public class CircleModel { private int value; PropertyChangeSupport props; ■ Controller: zur Verarbeitung von Benutzerereignis, Auslösen der Datenänderung public CircleModel(int value) { this.value = value; props = new PropertyChangeSupport(this); } ■ PropertyChangeSupport: Hilfsklasse für die Verarbeitung von Properties ■ ■ ■ public void setValue(int val) { old = value; value = val; props.firePropertyChange("value",old,val); } PropertyChangeEvent: Event der geschickt wird addPropertyChangeListener () firePropertyChange(String, Object, Object) public int getValue() {return value;} public void grow() {setValue(value+1);} public void addPropertyChangeListener(PropertyChangeListener list){ props.addPropertyChangeListener(list); } } School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 33 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 34 von 62 AWT Komponenten ■ Mittels dem AWT und dessen Komponenten lassen sich einfache GUIs erstellen ■ primär für Applets ■ Im AWT Paket ist der Event Mechanismus definier: import java.awt.event.* ■ Dieser wird auch in Swing bzw. JFC verwendet ■ AWT (Abstract Windows Toolkit) JFC enthält einen wesentlich reichhaltigeren Satz von GUI Komponenten (-> später) ■ Verschiedenen graphischen Komponenten des AWT ■ ■ ■ ■ Button TextField Label ScrollBar ■List ■TextArea ■Checkbox ■Choice (ComboBox) ■Canvas ■... School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 35 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 36 von 62 AWT Klassenhierarchie (vereinfacht) Abstrakte Oberklasse: Component ■ Component ist die abstrakte Object gemeinsame Oberklasse Component einfache Komponenten Oberklasse der meisten GUIKomponenten des AWT Klassenhierarchie der GUIKomponenten: Behälter für andere Komponenten ■ Component enthält viele Methoden, die von den GUI Komponenten geerbt bzw. überschrieben werden: ■ setBackground(Color farbe) setzt Hintergrundfarbe einer Komponente auf farbe ■ setForeground(Color farbe) setzt Vordergrundfarbe einer Komponent auf farbe ■ setFont(Font font) setzt Font einer Komponente auf font Button Scrollbar Checkbox Choice Label Canvas Container ■ Component ■ TextComponent ■ ■ Panel Hilfsklasse für Checkbox Textfield TextArea ■ Applet CheckboxGroup BorderLayout Hilfsklassen zur Anordnungssteuerung Frame Dialog ■ ■ FlowLayout School of Engineering ■ BoxLayout auf dem Desktop darstellbare Behälter © A. Meier/M. Braschler/J. Zeman/K. Rege ■ 37 von 62 Button Canvas Choice Container ■ Panel ■ Applet Label List Scrollbar TextComponent ■ TextArea ■ TextField School of Engineering ■ Color getBackground() gibt die entsprechenden Werte der Komponente aus ■ Color getForeground() ■ Font getFont() ■ paint(Graphics g) zeichnet die Komponente repaint() veranlasst AWT, die Methode update() der Komponente (sobald als möglich) aufzurufen ■ update() löscht den Bildschirmausschnitt, der der Komponente entspricht, und ruft dann paint() auf ■ setVisible(boolean b) macht entsprechende Komponente (un)sichtbar © A. Meier/M. Braschler/J. Zeman/K. Rege 38 von 62 Textkomponenten Oberklasse: TextComponent ■ ist abstrakte Oberklasse der Klassen TextField und TextArea: TextComponent definiert verschiedene Methoden, die von TextField und TextArea geerbt werden: ■ setEditable(boolean b) ■ boolean isEditable() ■ ■ String getText() Zeilenende ist jeweils mit "\n" markiert setText(String Text) markieren. int getSelectionStart() gibt Startindex des selektierten Textes zurück ■ int getSelectionEnd() gibt EndIndex des selektierten Textes zurück ■ String getSelectedText() gibt den selektierten Text selbst zurück ■ select(int startidx ,int endidx) selektiert Text zwischen startidx und endidx ■ selectAll() selektiert gesamten Text im Textfeld ■ addTextListener(Object lis) registriert ein Objekt als TextListener bei der Textkomponente. Das Listenerobjekt wird informiert, sobald sich der Text in der Textkomponente geändert hat. Der TextListener muss dazu die Methode public void textValueChanged(TextEvent e) deklarieren. ■ School of Engineering macht die Textkomponente editierbar oder nicht, je nach Wert von b gibt zurück, ob Textkomponente editierbar ist liest den ganzen Text aus dem Textfeld aus setzt Text in das Textfeld. Zeilenumbrüche mit © A. Meier/M. Braschler/J. Zeman/K. Rege TextField, TextArea und Label "\n" 39 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 40 von 62 TextField und TextArea Textzeile (TextField) ■ Klassen TextField und TextArea sind Unterklassen der Klasse TextComponent ■ TextField ist für einzeilige Eingaben (und Ausgaben) gedacht ■ Bei TextField nur eine Zeile eingebbar. ■ Der eingegebene Text kann beliebig editiert werden, bis die Eingabe durch Drücken der Enter-Taste bestätigt wird ■ Bei TextArea Eingabe beliebiger Anzahl Zeilen möglich ■ Löst ActionEvents aus ■ TextArea hat 2 Scrollbars ■ Anwendungsbeispiel: ■ Deklaration eines Textfeldes (3 Möglichkeiten): ■ ■ ■ ■ TextArea t = new TextArea(); TextArea t = new TextArea("1. Zeile\n2.Zeile"); erzeugt ein Textfeld mit den 2 Zeilen. TextArea t = new TextArea(anzReihen, anzKolonnen); ■ Nützliche Methoden (zusätzlich zu denen, die in Klasse TextComponent definiert sind): ■ ■ ■ ■ insert(String text, int idx) fügt text an der Stelle idx ins Textfeld ein replaceRange(String text, int startindex, int endindex) ersetzt Text zwischen startindex und endindex des Textfeldes durch text append(String text) hängt text am Ende des Textfeldes an School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 41 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege Textzeile erzeugen …Textfield: Demo-Applikation ■ Applet als ActionListener deklarieren. import java.applet.*; import java.awt.*; import java.awt.event.*; public class L8_Textfeld_Waehlerkontrolle extends Applet implements ActionListener { private TextField eingabe; // Instanzvariablen: GUI-Objekt(Komponente) Textfield private int alter; // alter: ermöglicht Datenaustausch zw. 2 Methoden ■ TextField-Variable deklarieren: TextField eingabe; ■ Textzeile erzeugen: eingabe = new TextField(10); ■ 10 bedeutet die maximale Anzahl angezeigter Zeichen public void init() { eingabe = new TextField(10); add(eingabe); eingabe.addActionListener(this); } ■ Textzeile zu Applet hinzufügen: add(eingabe); ■ Applet als Listener registrieren: eingabe.addActionListener(this); ■ Um den Text in der Textzeile zu verarbeiten, stellt die Komponente verschiedene Methoden zur Verfügung: ■ Aufbau GUI Komponente instanzieren zur GUI addieren Ereignis-Listener addieren public void actionPerformed(ActionEvent event) { if (event.getSource() == eingabe){ alter = Integer.parseInt(eingabe.getText()); } repaint(); } ■ Methode actionPerformed schreiben. ■ // // // // public void paint (Graphics g) { g.drawString("Alter ist " + alter, 50, 80); if (alter >= 18){ g.drawString("Stimmberechtigt", 50, 100); else { g.drawString("Zu jung!", 50,100); } } Text von der Textzeile einlesen: eingabe.getText() Text in Textzeile schreiben: eingabe.setText("Text") 42 von 62 // Textfeld auslesen und wandeln } } School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 43 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 44 von 62 Label ■ Labels sind Beschriftungen mit einem fixen Text ■ Erbt nicht von TextComponent ■ Ein Label-Objekt kann mit folgender Anweisung erzeugt werden (als lokale Variable): Label labelVariable = new Label("Labeltext"); ■ Labeltext ist der Text der Beschriftung Scrollbar ■ Labels verhalten sich wie andere Komponenten (Scrollbar, Button, etc.) ■ Label erzeugen keine Ereignisse! School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 45 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege Schieberegler (Scrollbar, Slider) Schieberegler Graphik ■ Der Scrollbar kann durch das Verschieben des Balkens oder durch Drücken auf die Pfeile betätigt werden. Dabei verschiebt er sich mit der konstanten Schrittweite 1 pro Ereignis. ■ Beispiel: Programm ScrollbarValues ■ Beim Erzeugen eines Scrollbars kann die Ausrichtung des Scrollbars, der Minimal- und Maximalwert, der Startwert sowie die Grösse der Schrittweite angegeben werden 46 von 62 public void adjustmentValueChanged(AdjustmentEvent e) { Graphics g = getGraphics(); currentX = slider.getValue(); g.drawLine(0, currentY, currentX, currentY); currentY = currentY+5; } ■ Im Gegensatz zu Buttons und Textzeilen erzeugen Scrollbar Ereignisse der Klasse AdjustmentEvent ■ Scrollbar ruft bei jeder Verschiebung der Balkens die Methode adjustmentValueChanged(AdjustmentEvent e) auf ■ Aktueller Wert kann mit der Methode getValue() abgefragt werden School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 47 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 48 von 62 Schieberegler …Schieberegler : Anwendungsbeispiel Scrollbar (Auszug aus der Klassenbibliothek: Constructor) public class L8_Scrollbar extends Applet implements AdjustmentListener{ private Scrollbar slider; // Instanzvariablen private int sliderValue = 0; public Scrollbar (int int int int int Parameters: orientation, value, visible, minimum, maximum) public void init() { // GUI aufbauen setLayout(null); // kein Layout -> Komponenten von Hand positioniert und skaliert slider = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 1, 100); slider.setBounds(100,10, 200, 20); // Slider-Grösse. x,y,width, height add(slider); slider.addAdjustmentListener(this); } orientation - indicates the orientation of the scroll bar. (Scrollbar.HORIZONTAL, or Scrollbar.VERTICAL) value - the initial value of the scroll bar visible - the size of the scroll bar's bubble, representing the visible portion minimum - the minimum value of the scroll bar maximum - the maximum value of the scroll bar public void paint(Graphics g) { g.drawString("Aktueller Schiebereglerwert: "+sliderValue, 100, 100); g.setColor(Color.GREEN); g.fillRect(100,150,sliderValue*2, 30); // Slider-Wert als Balken } public void adjustmentValueChanged(AdjustmentEvent e){ sliderValue = slider.getValue(); repaint(); } ■ Beispiel: () Skript, Schieberegler.java) slider = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100); } School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 49 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 50 von 62 Skalierung des Schiebereglerwertes … Skalierung des Schiebereglerwertes ■ Problem: Bei der Verwendung von Scrollbar tritt häufig folgendes Problem ■ Beispiel: Der gewünschte Scrollbar-Bereich im Progamm InchesToCm soll auf: ■ ■ 0.0-10.0 sein mit einer Schrittweite von 0.1 Man möchte mit dem Scrollbar beispielsweise Werte zwischen 0.0 und 10.0 in 0.1-Schritten einstellen Die kleinste Schrittweite bei einem Scrollbar ist aber 1, da nur int-Zahlen als Scrollbar-Werte erlaubt sind ■ Minimum, Maximum und Inkrement des Scrollbars auf 0, 100 bzw. 1 setzen: slider = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100); ■ Ausgelesener Scrollbar-Wert jeweils durch 10 dividieren: ■ Lösung: Die vom Scrollbar zurückgegebenen Werte werden skaliert sliderValue = (double) slider.getValue()/10; School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 51 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 52 von 62 Lernaufgabe (Lösung im Anhang) Zwei Slider mit je einem Label für die Ausgabe Ausgabe des Programms: Einführung Anordnung, Layouts School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 53 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 54 von 62 Einfache Anordnung von GUI-Komponenten Null Layout ■ Java ordnet die GUI Komponenten automatisch an (=Layout) ■ Mittels setLayout(null) kann der Layoutmanager entfernt werden ■ Wenn nichts anderes angegeben wird, werden die Komponenten in einem Applet nach einem FlowLayout angeordnet ■ Wird kein Layout angegeben, dass müssen die Komponenten Komponenten von Hand positioniert und skaliert werden ■ Layout definiert "Strategie", wie die Komponenten angeordnet werden ■ ■ Die Komponenten werden zeilenweise zentriert aufgereiht Wenn eine Zeile voll ist, werden die restlichen Komponenten auf einer neuen Zeile dargestellt public void init() { // GUI aufbauen setLayout(null); // kein Layout slider = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 1, 100); slider.setBounds(100,10, 200, 20); // Slider-Grösse. x,y,width, height add(slider); slider.addAdjustmentListener(this); } ■ FlowLayout nicht für "hochwertige" GUIs geeignet ■ z.B. FlowLayout skaliert die Scrollbars automatisch Æ werden sehr klein Abhilfe: andere Layouts definieren (z.B. Border- oder GridLayout Æ später) oder einfach "null"-Layout verwenden School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 55 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 56 von 62 Zusammenfassung Anhang: Applet Methoden Zusammenfassung der Methoden, die der Programmierer schreibt, um die View und den Controller für ein Model bereitzustellen: ■ Ereignisse ■ Entwurf von interaktiven Anwendungen: Modell, View, Controller ■ AWT (Abstract Windows Toolkit) ■ TextField, TextArea und Label Methode Wird aufgerufen, wenn Aufgabe init das Applet gestartet wird 1. Erzeugt die Objekte für das Modell 2. Erzeugt beliebige Widgets, die gebraucht werden actionPerformed der Benutzer eine Schaltfläche drückt Handhabt das Ereignis, indem sie Anweisungen an das Modell weitergibt (Aufruf einer Methode im Modellobjekt) paint eine Veränderung angezeigt werden soll – das Fenster muss neu gezeichnet wrdn. Zeigt alles an, was im Fenster angezeigt werden muss ■ Scrollbar ■ Einführung Anordnung, Layouts School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 57 von 62 Anhang: paint vs. repaint School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege Komponenten und Ereignisklassen des AWT ■ Es gibt einen entscheidenden Unterschied zwischen paint und repaint Ereignisklassen ■ paint(): wird vom Programmierer zur Verfügung gestellt und vom Browser aufgerufen ■ repaint(): wird von der Bibliothek zur Verfügung gestellt und vom Programmierer aufgerufen Events Generated by AWT Components This table lists the kinds of events that each 1.1 AWT component can generate. Methode Wird aufgerufen, wenn Aufgabe paint der Fensterinhalt neu gezeichnet werden muss Zeichnet den Fensterinhalt repaint sich das Modell verändert hat und deshalb die View des Models im Fenster verändert werden muss Informiert den Browser darüber, dass sich etwas im Fenster verändert hat und dass es deshalb neu gezeichnet werden muss School of Engineering 58 von 62 © A. Meier/M. Braschler/J. Zeman/K. Rege 59 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 60 von 62 Listener Interfaces und Methoden des AWT Anhang: Lösung Listener import java.awt.*; import java.applet.Applet; import java.awt.event.*; ■ Um Events zu behandeln, muss das entsprechende Listener Interface implementiert werden public class LabelDemo extends Applet implements AdjustmentListener { private Scrollbar bar1, bar2; private int bar1Value = 0, bar2Value = 0; ■ Um ein Listener Interface zu implementieren, müssen alle in der Tabelle aufgeführten Methods im Applet programmiert werden public void init() { Label title1, title2; title1 = new Label("up:"); add(title1); bar1 = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100); add(bar1); bar1.addAdjustmentListener(this); title2 = new Label("down:"); add(title2); bar2 = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100); add(bar2); bar2.addAdjustmentListener(this); } public void paint(Graphics g) { g.drawString("UP value is " + bar1Value, 100, 100); g.drawString("DOWN value is " + bar2Value, 100, 150); } public void adjustmentValueChanged(AdjustmentEvent e) { bar1Value = bar1.getValue(); bar2Value = bar2.getValue(); repaint(); } ■ Bsp. ActionListener muss actionPerformed( ActionEvent e) implementieren } School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 61 von 62 School of Engineering © A. Meier/M. Braschler/J. Zeman/K. Rege 62 von 62