Telecooperation/RBG
Technische Universität Darmstadt
Copyrighted material; for TUD student use only
Grundlagen der Informatik 1Thema 21: GUI und verschachtelte Klassen
Prof. Dr. Max MühlhäuserDr. Guido Rößling
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
AWT und Swing• AWT = Abstract Window Toolkit
– Package java.awt– Benutzt Steuerelemente des darunterliegenden
Betriebssystems• Native Code (= direkt für die Maschine geschrieben, keine
VM)• schnell• Aussehen (Look) hängt vom System ab: unterschiedliche
Schriften, …• Portabilität eingeschränkt
• Swing– Package javax.swing (Teil der Java Foundation Classes)– Merkmal: Swing-Klassen beginnen mit „J“: JButton, ...– Vollständig in Java programmiert, eigener Look– Baut auf AWT auf– Verwendet ein Minimum an systemspezifischen Komponenten
2
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Komponenten
• Einige oft verwendete Komponenten und für welche Interaktionsaufgaben sie verwendet werden
• Anzeigen von Textund Symbolen– JLabel
• Auslösen von Aktionen– JButton
– JMenu– JMenuItem
3
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Komponenten
• Eingabe von Text– JTextField
• Auswahl aus einer festen Menge von Optionen– JCheckBox
• Auswahl aus einer variablen Menge– JList
4
gegenseitig ausschließend: JRadioButton
JComboBox
Button oder TextField +ausklappbare Listbox
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Menschliche Faktoren
• Beim Entwurf interaktiver Programme gibt es neben der funktionalen Vollständigkeit und Korrektheit viele zusätzliche Aspekte zu beachten
• Dazu gehört die Art und Weise der Interaktion und wie leicht sie zu erlernen und benutzen ist
• Richtlinien für gute GUIs sind u.a.:– Vermeide Modi. Allgemein sinnvolle Operationen
sollten immer verfügbar sein.– Biete einfache und durchgängige
Interaktionssequenzen an.– Überfordere den Benutzer nicht durch zu viele
Optionen.– Zeige bei jeder Interaktionsstufe klar die verfügbaren
Optionen.– Gib dem Benutzer angemessene Rückmeldungen.– Gib dem Benutzer die Möglichkeit, Fehler problemlos
rückgängig zu machen.
5
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Anatomie einer GUI-Applikation
• Komponenten• Container• Ereignisse• Listener• Layout
– Legt die Anordnungder Komponenten fest
• Look & Feel– Legt das Aussehen
der Komponenten fest
• getrennt: Anwendungslogik
6
Anwendungslogik
Zustand:wert=3
GUI-Framework
Ereignisse Methodenaufrufeauf Komponente
Komponenten
Container
Listener
Netz von kooperierenden Objekten mit klar festgelegten Zuständigkeiten:
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Fäden (Threads)• Sequentielle Programme
– haben Anfang, definierte Ausführungssequenz und Ende.– Zu jedem Zeitpunkt ist genau eine Anweisung aktiv.– Ein Faden (Thread) ist ein einzelner sequentieller
Kontrollfluss in einem Programm.
• Nebenläufige Programme– Programme können mehrere Fäden besitzen.– Mehrere Programmteile können so quasi gleichzeitig
ablaufen.
7
Faden
Programm
Fäden
Programm
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Fäden (Threads)
• Fäden (Threads)…– nutzen die Ressourcen des Prozesses mit, in dem sie
ablaufen– besitzen keine eigenen Speichersegmente– verfügen über einen eigenen Registersatz (inkl.
Programmzähler und Statusregister) sowie einen eigenen Stack
– werden oft auch als leichtgewichtige Prozesse (lightweight processes) bezeichnet.
• GUI-Applikationen besitzen neben dem Haupt-Thread einen sogenannten Event-Dispatching Thread– Dieser Thread ruft Methoden der Anwendung auf, wenn
bestimmte Ereignisse auftreten (Callback)– Die Ereignisbehandlungsroutinen in der Anwendung werden
sequentiell ausgeführt– Das Zeichnen von Komponenten wird ebenfalls im Kontext
dieses Threads ausgeführt8
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
AWT-EventQueue
AWT-EventQueue AWT-EventQueue
main
Programmiermodell
9
Anwendung GUI-Framework (SWING)
Komponente einfügen
Ereignis:Komponente zeichnen
Ereignis:Benutzereingabe
main
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Fensterimport javax.swing.JFrame;
public class GUITest extends JFrame { // The width of the window in pixels public static final int WIDTH = 400; // The height of the window in pixels public static final int HEIGHT = 300; // Constructs a new window with a given title public GUITest(String title) { super(title); } // Start test application. Creates a new window and displays it public static void main(String args[]) { // Construct a new window. It is initially invisible GUITest theWindow = new GUITest("My first GUI Application"); // Set width and height of the window theWindow.setSize(WIDTH, HEIGHT); // Open the window theWindow.setVisible(true);
System.out.println("Exiting main..."); }}
10
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Fenster
• Wir beobachten...– main() wird verlassen, das Programm läuft aber
weiter.Mehrere Fäden.
Der Event-Dispatching Thread läuft weiter.– Klick auf Schließen-Button beendet das Programm
nicht.Ereignisverarbeitung fehlt.
Genaueres dazu später.11
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Container
• Container und Komponenten– JFrame: „top level container“
• benutzt Fenster vom Betriebssystem– JPanel: „intermediate container“
• dient zum Gruppieren und Anordnen von Komponenten
• Verschachtelung möglich– JLabel, JButton, ...: „atomare Komponenten“
• präsentieren dem Benutzer Informationen• erlauben oft Interaktion und Eingabe
(Steuerelemente)• Container-Hierarchie
– Selbst die einfachste Anwendung besteht auseiner Hierarchie von Containern und Komponenten
– (Darstellung vereinfacht. Die Container zwischen JFrame und JPanel werden hier nicht weiter betrachtet) 12
JFrame
JPanel
JLabel
JFrame
JPanel
JLabel
...
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Komponenten
• Hinzufügen von Komponenten– Der JFrame erzeugt automatisch ein JPanel,
das „contentPane“.– Darin kann die Anwendung neue
Komponenten einfügen.– Die Komponenten werden eingefügt, während
das Fenster noch unsichtbar ist, also zwischendem Erstellen des Fenster-Objekts mit new undder Anzeige mit setVisible(true).
• JLabels– stellen Text oder/und Symbole dar– sind passive Komponenten, erlauben keine
Interaktion
13
JFrame
JPanel
JLabel
...
contentPane
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
import java.awt.Container;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame { public GUITest(String title) { super(title);
// Retrieve the area where one can add elements Container pane = getContentPane();
// Create a new label that displays help information JLabel label = new JLabel( "Press the [X] in the top right corner to exit");
// Add the label to the content of the window pane.add(label); } // ...}
Labels
14
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Buttons
import java.awt.Container;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame { public GUITest(String title) { super(title);
Container pane = getContentPane();
JLabel label = new JLabel( "Press the [Exit] or [X] in the top right corner to exit");
pane.add(label); // Create a new push button that may be used in addition to the [X] JButton button = new JButton("Exit");
// Add the button to the content of the window pane.add(button); } // ...}
15
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Layout
• Wir beobachten...– Der Text ist nicht mehr sichtbar, denn der Button liegt
darüber!• Layout-Management
– ist der Prozess, die Größe und Position von Komponenten zu bestimmen.
– Das gewünschte Layout wird durch Zuordnung eines Layout-Objekts zum Container festgelegt:
Container pane = getContentPane();pane.setLayout(new GridLayout(ROWS, COLS));
– Die Layout-Klasse implementiert das Interface LayoutManager.
16
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Vordefinierte Layouts
• GridLayout– Ordnet die Komponenten in einem
rechteckigen Gitter an.– Die Reihenfolge des Einfügens der
Komponenten bestimmt ihre Anordnung.• BorderLayout
– Positioniert in 5 Regionen jeweilsmaximal eine Komponente
– Die Regionen N, E, S und W werdenso klein wie möglich gehalten. Derrestliche Platz entfällt auf CENTER.
– Zuordnung zu einer Region durch zusätzlichen Parameter beim Aufruf von Container.add:add(new Button("SOUTH"), BorderLayout.SOUTH);
• Weitere Layouts: BoxLayout, FlowLayout, GridBagLayout, ...– Siehe die Java API Dokumentation und die Tutorials für mehr
Informationen17
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
GridLayout
import java.awt.Container;import java.awt.GridLayout;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame { public GUITest(String title) { super(title); Container pane = getContentPane();
// Define a LayoutManager that places new elements properly // onto the pane. Here we use a grid with 3 rows and 1 column. pane.setLayout(new GridLayout(3, 1));
JLabel label = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(label); JButton button = new JButton("Exit"); pane.add(button); } ...}
18
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Ereignisse (Events)
• Jedesmal, wenn der Benutzer eine Taste drückt oder die Maus bewegt, tritt ein Ereignis ein.
• Steuerelemente können Maus- und Tastatur-Ereignisse verarbeiten und neue Ereignisse erzeugen.– Beispiel: Befindet sich der Mauszeiger über einem Button
und die Maustaste wird losgelassen, dann wird ein ActionEvent erzeugt.
• Ereignisse werden durch Event-Objekte beschrieben– Die zugehörigen Klassen sind von java.awt.AWTEvent
abgeleitet. (für GUI; allgemeiner: java.util.EventObject)– Der Typ gibt Auskunft über die Art des Ereignisses:
ActionEvent: Benutzer klickt einen Button, drückt Return in einem Textfeld, wählt einen
Menüeintrag, ...WindowEvent: Benutzer schließt Fenster, ......
– Die Attribute geben zusätzliche Informationen über das Ereignis, z.B. welcher Button gedrückt wurde.
19
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Listener
• Mehrere Listener können sich bei einer Ereignis-Quelle (event source) registrieren und werden von diesem Zeitpunkt an über Ereignisse eines bestimmten Typs informiert.
• Programmieren eines Listeners:– Das Klasse des Empfänger-Objekts (event listener) muss
das dem Ereignistypen entsprechende Interface implementieren.
• Z.B. für ActionEvents das Interface ActionListener.– Die Klasse muss alle Methoden des Interface
implementieren.– Der Klient registriert nun das Empfänger-Objekt bei der
Ereignis-Quelle. Z.B. mittels addActionListener(Listener)
20
eventsource
event objectevent listener
event listener
event listener
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Ereignisseimport java.awt.Container;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame { public GUITest(String title) { super(title);
Container pane = getContentPane(); pane.setLayout(new GridLayout(3, 1)); JLabel label = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(label); pane.add(new JButton("Exit"));
// Create another button that changes the text of the Label JButton button = new JButton("Change Label Text");
// Now, define what should happen if the button is pressed button.addActionListener(new ChangeButtonListener()); pane.add(button); }
private class ChangeButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { System.out.println("Change Label Text was clicked"); } } // ... }
21
Das ist eine verschachtelte Klasse (nested class). Später mehr dazu!
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
View-Updates
• Die durch Komponenten dargestellten Informationen und ihr Aussehen können durch Aufrufen ihrer Methoden verändert werden.
• JLabel-API (Auszug):
22
void setText(String)String getText()
Setzen oder auslesen des dargestellten Texts
void setHorizontalAlignment(int)int getHorizontalAlignment()
Textausrichtung: LEFT, CENTER oder RIGHT
void setVerticalAlignment(int)int getVerticalAlignment()
Textausrichtung: TOP, CENTER oder BOTTOM
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Ereignisseimport java.awt.Container;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame {
private JLabel infoLabel; public GUITest(String title) { super(title);
Container pane = getContentPane(); pane.setLayout(new GridLayout(3, 1));
infoLabel = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(infoLabel); pane.add(new JButton("Exit"));
// Create another button that changes the text of the Label JButton button = new JButton("Change Label Text");
// Now, define what should happen if the button is pressed button.addActionListener(new ChangeButtonListener()); pane.add(button); } private class ChangeButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { infoLabel.setText("You clicked the button! Now [Exit] or [X]"); } } // ...}
23
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Window-Events
• Beim Klicken auf den Schließen-Button soll das Programm nun korrekt beendet werden. Registrieren eines WindowListeners
• Interface WindowListener:
24
void windowActivated(WindowEvent e)
Window wurde aktiviert
void windowClosed(WindowEvent e) Fenster wurde nach dispose() geschlossen
void windowClosing(WindowEvent e) Benutzer hat auf „Schließen“ geklickt
void windowDeactivated(WindowEvent e)
Fenster wurde deaktiviert
void windowDeiconified(WindowEvent e)
Fenster wurde de-minimiert
void windowIconified(WindowEvent e) Fenster wurde minimiert
void windowOpened(WindowEvent e) Fenster wurde gerade geöffnet
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Adapter
• Beim Verwenden von Interfaces müssen immer alle Methoden implementiert werden. Das ist oft unpraktisch, deshalb existieren Adapter.
• WindowAdapter…– implementiert WindowListener– definiert alle Methoden mit leerem Rumpf und somit
ohne Verhalten– ist eine abstrakte Klasse.
• Der anwendungsspezifische Event-Handler wird nun von WindowAdapter abgeleitet und überschreibt nur die „interessanten“ Methoden.
25
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
WindowEvents
import java.awt.Container;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;
public class GUITest extends JFrame { private JLabel infoLabel; public GUITest(String title) { super(title);
// Now, also define that the [X] terminates the program correctly addWindowListener(new MyWindowListener());
Container pane = getContentPane(); pane.setLayout(new GridLayout(3, 1)); infoLabel = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(infoLabel);
// Create a new push button that may be used in addition to the [X]
JButton button = new JButton("Exit");
// Define that the program should exit if you click the button button.addActionListener(new ExitButtonListener()); pane.add(button);
26
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Window Events // Create another button that changes the text of the Label button = new JButton("Change Label Text"); // Now, define what should happen if the button is pressed button.addActionListener(new ChangeButtonListener()); pane.add(button); } private class ChangeButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { infoLabel.setText("You clicked the button! Now [Exit] or [X]"); } }
// Exit the program when the window close button is clicked class MyWindowListener extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } // Exit the program when the “Exit”-button is clicked class ExitButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { System.exit(0); } } public static void main(String args[]) { GUITest theWindow = new GUITest("My first GUI Application"); theWindow.setSize(WIDTH, HEIGHT); theWindow.setVisible(true); } public static final int WIDTH = 400; public static final int HEIGHT = 300;}
27
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Verschachtelte Klassen: Motivation
• Die GUI Komponenten erwarten als “Listener” eine Instanz von XYZListener (z.B. ActionListener)
• Wie können wir ein passendes Listener Objekt erstellen?
• Option 1: Frame-Klasse implementiert das Listener Interface direkt
• Option 2: Externe Klasse implementiert das Listener Interface
28
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Option 1: Frame-Klasse implementiertdas Listener Interface direkt
import java.awt.Container;import java.awt.GridLayout;
import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame implements ActionListener { public GUITest(String title) { super(title);
Container pane = getContentPane(); pane.setLayout(new GridLayout(3, 1)); JLabel label = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(label); pane.add(new JButton("Exit"));
// Create another button that changes the text of the Label JButton button = new JButton("Change Label Text");
// Now, define what should happen if the button is pressed button.addActionListener(this); pane.add(button); }
public void actionPerformed(ActionEvent event) { System.out.println("Change Label Text was clicked"); } // ... }
29
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Option 1: Frame-Klasse implementiertdas Listener Interface direkt
• Diese Möglichkeit funktioniert zwar, ist aber im Allgemeinen unbefriedigend– Was ist, wenn es mehr als einen Button gibt?
• Klasse kann nicht zwei actionPerformed Methoden haben!
– Es gibt nicht nur Buttons, sondern auch Labels, Menus, …
• Frame-Klasse implementiert eine Menge an Interfaces, die nichts mit seiner eigentlichen Funktionalität zu tun haben
– action-Methoden müssen public sein, obwohl es eigentlich Implementationsdetails sind, die nicht zur Schnittstelle von Frame gehören
• Im Allgemeinen ist dies eine schlechte Lösung
30
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Option 2: Externe Klasse implementiertdas Listener Interface
import java.awt.Container;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame { private JLabel infoLabel; public GUITest(String title) { super(title);
Container pane = getContentPane(); pane.setLayout(new GridLayout(3, 1)); infoLabel = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(infoLabel); pane.add(new JButton("Exit"));
// Create another button that changes the text of the Label JButton button = new JButton("Change Label Text");
// Now, define what should happen if the button is pressed button.addActionListener(new ChangeButtonListener()); pane.add(button); }}
class ChangeButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { infoLabel.setText("You clicked the button! Now [Exit] or [X]"); }}
31
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Option 2: Externe Klasseimplementiert das Listener Interface
• Hat nicht die konzeptuellen Nachteile von Option 1– z.B. kein Problem, unterschiedliche Aktionen für
unterschiedliche Buttons zu definieren– Das Interface des Frames wird nicht verunstaltet
• Nachteile dieses Ansatzes– Führt zu sehr vielen Klassen
• Übersichtlichkeit leidet– Geringere Kohäsion
• Externe Listener-Klasse wird evtl. nur an genau einer Stelle benutzt
– Aufwändig und lästig, für jeden Listener eine eigene Klasse anzulegen
– Zugriff auf Instanzvariablen/Methoden/lokale Variablen der Frame Klasse aufwändig
• Alles muss explizit im Konstruktor übergeben werden
32
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Option 2: Externe Klasseimplementiert das Listener Interface
import java.awt.Container;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame { private JLabel infoLabel; public GUITest(String title) { super(title);
Container pane = getContentPane(); pane.setLayout(new GridLayout(3, 1)); infoLabel = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(infoLabel); pane.add(new JButton("Exit"));
// Create another button that changes the text of the Label JButton button = new JButton("Change Label Text");
// Now, define what should happen if the button is pressed button.addActionListener(new ChangeButtonListener(infoLabel)); pane.add(button); }}class ChangeButtonListener implements ActionListener { private JLabel infoLabel; public ChangeButtonListener(JLabel l) { infoLabel = l; } public void actionPerformed(ActionEvent event) { infoLabel.setText("You clicked the button! Now [Exit] or [X]"); }}
33
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Verschachtelte Klassen
• Beide Möglichkeiten (Option 1 + Option 2) sind nicht zufriedenstellend
• Dies war die Hauptmotivation für Sun, mit Java 1.1 die verschachtelten Klassen (nested classes) einzuführen
• Verschachtelte Klassen sind Klassen innerhalb von Klassen– Werden deklariert wie ganz normale Klassen,
außer dass sie innerhalb anderer Klassen stehen– Einige Zugriffsregeln sind anders– Verschachtelte Klassen haben Zugriff auf
Instanzvariablen/Methoden der äußeren Klasse
34
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Verschachtelte Klassen
import java.awt.Container;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame { private JLabel infoLabel; public GUITest(String title) { super(title);
Container pane = getContentPane(); pane.setLayout(new GridLayout(3, 1)); infoLabel = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(infoLabel); pane.add(new JButton("Exit"));
// Create another button that changes the text of the Label JButton button = new JButton("Change Label Text");
// Now, define what should happen if the button is pressed button.addActionListener(new ChangeButtonListener()); pane.add(button); } private class ChangeButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { infoLabel.setText("You clicked the button! Now [Exit] or [X]"); } } // ...}
35
- Nested Class kann “private” sein- Klasse nur innerhalb der umschließenden Klasse
sichtbar- hat Zugriff auf private Instanzvariable der
umschließenden Klasse
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Verschachtelte Klassen
• Jede verschachtelte Klasse benötigt bei der Instanziierung eine Referenz auf eine Instanz der umschließenden Klasse– Bei Instanziierung innerhalb der umschließenden Klasse
wird diese Referenz implizit übergeben– Außerhalb einer umschließenden Klasse als
enclInstance.new MyInnerClass()– Der Typ einer nested Class N innerhalb C ist “C.N”
• Innerhalb von C reicht die Typdeklaration N (implizites Scoping)
– Daumenregel: Wenn der Name einer nested class außerhalb der umschließenden Klasse benötigt wird, hat man etwas falsch gemacht.
• Verschachtelte Klassen können auch als “static” deklariert werden– Semantik analog zu static method: Kein Zugriff auf
Instanzvariablen der äußeren Klasse, sondern nur auf static Methoden/Variablen
36
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Anonyme verschachtelte Klassenimport java.awt.Container;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;
public class GUITest extends JFrame {public GUITest(String title) { super(title);
final JLabel infoLabel; // now a local variable Container pane = getContentPane(); pane.setLayout(new GridLayout(3, 1));
infoLabel = new JLabel( "Press the [Exit] or [X] in the top right corner to exit"); pane.add(infoLabel); pane.add(new JButton("Exit"));
// Create another button that changes the text of the Label JButton button = new JButton("Change Label Text");
// Now, define what should happen if the button is pressed button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { infoLabel.setText("You clicked the button! Now [Exit] or [X]"); } }); pane.add(button); }}
37
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Anonyme verschachtelte Klassen
• Man kann innerhalb von Methoden anonyme Klassen anlegen– Diese haben keinen Namen– Sie werden nur über Supertypen angesprochen– Syntax: new SuperClassName(args) { … } odernew InterfaceName() { … }
– Erzeugt implizit eine Subklasse der angegebenen Superklasse bzw. eine Klasse, die das angegebene Interface implementiert
– Gleichzeitig wird eine Instanz der anonymen Klasse erzeugt
– Diese Klasse kann über den angegebenen Superklassen/Interface Namen benutzt werden
– Sogar lokale Variablen der Methode können in der Implementierung verwendet werden, sofern sie als “final” deklariert sind
38
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Anonyme verschachtelte Klassen• Vorteil gegenüber “normalen” verschachtelten
Klassen– Wenn die Klasse nur an einem einzigen Ort benötigt wird,
wird kein Name “verschwendet”– Definition der Klasse “on the fly” – dort wo sie benötigt
wird– Einfacher Zugriff auf lokale Variablen /
Methodenparameter
• Anonyme Klassen kommen dem “lambda” aus Scheme recht nahe– Mit “lambda” können in Scheme Prozeduren “on the fly”
definiert werden
39
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Kompilierung von verschachtelten Klassen
• Wenn eine verschachtelte Klasse kompiliert wird, bekommt man für jede verschachtelte Klasse ein eigenes .class file mit dem Namen “OuterClass$InnerClass.class”
• Wenn eine anonyme Klasse kompiliert wird, heißt das File “OuterClass$n.class”, wobei n eine ganze Zahl ist
• Intern (auf JVM Ebene) gibt es keine verschachtelten Klassen
• Der Compiler transformiert intern den Code– Für jede verschachtelte Klasse wird eine Top-Level Klasse
angelegt, die alle benötigten Argumente im Konstruktor übergeben bekommt
40
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
GUI und Software Design
• GUIs können sehr aufwändig und kompliziert sein• Die eigentliche Anwendung ebenfalls• Wie strukturiert man eine Anwendung mit komplexer
GUI?• Regel Nr.1:
41
Trennen Sie die Anwendungslogik von der Präsentationslogik
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
GUI Antipatterns
• Sie machen etwas falsch, wenn…– Sie in ihrer GUI-Klasse auf eine Datenbank zugreifen– Ihre GUI-Klasse mehr als 50 KB groß ist– in der GUI-Klasse Geschäftsprozesse implementiert
werden– Ihre Anwendungsdaten in GUI-Klassen gespeichert
sind– …
• Besser: Schichtenarchitektur– z.B. sog. “Model-View-Controller Architektur”
• trennt Daten/Anwendungslogik von Interaktion mit Benutzer
• Daten/Anwendungslogik hängt nicht von GUI ab
• einfach, mehrere Views zu unterstützen• Austausch von Views einfach
42
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Model-View-Controller
43
View
Model
controller updatesController
Hinweis
auf Ä
nder
ung
Zugrif
fAktualisieren
BehandeltNutzer-
eingabenAnzeige
Anwendungsdatenund Verhalten
A B C
45 35 15
Event senden
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
MVC – Das Modell
• Das Modell enthält die Daten • Hat Methoden, um auf Daten zuzugreifen und
sie zu ändern• Benachrichtigt Listener/Observer, wenn sich die
Daten ändern• Kann (Teile) der Geschäftsprozesse
implementieren
44
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
MVC – Der Controller
• Verarbeitet die Eingaben des Benutzers– zum Beispiel Validierung, Interpretation jeglicher Art, …
• Häufig zuständig für die Benutzerführung der GUI• Kommuniziert diese Eingaben zum Modell• Kann präsentationsnahe Teile der Anwendungslogik
enthalten– z.B. Interaktionsfluss mit dem Benutzer– Scharfe Trennung vom Modell ist oft schwierig
• Kann (muss aber nicht) spezifisch für eine feste GUI sein– Controller hat oder hat nicht eine Instanzvariable die auf die
GUI zeigt• evtl. entkoppelt über Interface
– Bessere Wiederverwendbarkeit im letzteren Fall• Schichtenstruktur
45
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
MVC – Die View
• Die View stellt eine visuelle Repräsentation des Modells dar
• Es kann beliebig viele Views auf denselben Daten geben– z.B. mehrere Instanzen derselben View– Aber auch völlig unterschiedliche Views– Zum Beispiel können die Finanzen einer Firma als Tabelle
oder als Graph dargestellt werden • Registriert sich beim Modell als Listener, zeichnet sich
neu, wenn Modell sich ändert.
46
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Internationalization (I18N)• Internationalisierung: Bereitstellung von Inhalten
in mehreren Sprachen• Problematisch für GUIs: was muss sich ändern?• Beispiel - Menüeintrag:
– Text– [optionales] Icon– Kürzel (hier: ALT+G)– Tool tip (“Generate…”)
• Englische Fassung:
47
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Internationalization (I18N)
• Java bietet Basiselemente für Internationalization• Die GUI-Anpassung muss aber vom Programmierer
erfolgen• Alternative: Nutzung des translator Package
– Siehe die Beispiele auf den folgenden Folien• Grundlegender Ansatz:
– Alle sprachspezifischen Elemente kommen in eine Datei• Eine Datei pro unterstützter Sprache
– Die Zeilen der Datei sind im Format key=Wert• key: ein String, der das Element beschreibt• Wert: der auszugebende Wert für den key
– Anstelle “echter” Texte wird im Code nur der key genutzt
48
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Sprachressourcen
• Alle Ressourcen kommen in die sprachspezifische Datei
• Diese Dateien haben alle den gleichen Basisnamen– Zum Beispiel “msg”
• Die Dateierweiterung hat das Format land_SPRACHE– Deutsche Ressourcen stehen also in “msg.de_DE”– Die US-Englische Fassung steht in “msg.en_US”– …
• Beispiel für einen Inhalt:
49
hi=Hello!query=How are you today?
hi=Hallo!query=Wie geht es Dir?
msg.en_US msg.de_DE
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
translator Package: Translator
• Ziel: Inhaltsübersetzung für eine Zielsprache• Nutzt java.util.Locale für die Sprachbestimmung
– Vordefinierte Locales: Locale.GERMANY, Locale.US, …– Die Zielausgabe hängt ab von bis zu drei Attributen:
• Sprache: “de”, “en”, “es”, …• Land: “de”, “us”, “uk”, …• Variante: spezifischer Code für Browser etc., z.B. „WIN”
• Anlegen einer neuen Instanz von Translator– Parameter: Basisname der Ressourcen und Ziel-Locale:Translator myTrans = new Translator(“msg”,
Locale.GERMANY);
50
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
translator Package: Translator
• Übersetzen einer Nachricht überString myTrans.translateMessage(key)
• Beispiel:– myTrans.translateMessage("hi") Hallo!
• Manchmal muss die Ausgabe parametrisiert werden– Wie begrüßt man eine Person? “Hallo, Herr Schmidt!”
51
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Übersetzen parametrisierter Texte
• Das Package unterstützt Parameter in {}:– Angenommen, wir haben diese Definition in unserer
Datei: personalized=Hallo, {0}!– Nun können wir einen Parameter übergeben…:myTrans.translateMessage("personalized", "Herr Schmidt");
Hallo, Herr Schmidt!
• Parameter werden als Zahl ab 0 in {} gesetzt• Wenn mehr als ein Parameter erforderlich ist, …
– kommen diese in ein Array: translateMessage(key, Object[])
– übergibt man sie als Strings: translateMessage(key, String…)
52
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Internationalisierte GUI-Anwendung
• Wir werden nun eine kleine GUI-Anwendung bauen– Ein JFrame dient als Hauptfenster– Mit einem JMenuBar
• Mit einem “Datei”-Menü– Das hat einen “Exit”-Eintrag
– Zwei umrahmte JPanel:• Eines mit einem JLabel und einem JButton• Das zweite hat nur einen “Beenden” JButton mit Icon
• Jeder Klick auf den Button erhöht einen Zähler• Verlässt man die Anwendung über den Beenden-
Button, wird die Anzahl Klicks angezeigt• Keine Sorge, das ist einfacher als es wirkt…
53
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
I18N GUI Demo – Code I
import translator.TranslatableGUIElement; // for GUI elementsimport translator.Translator; // for I18N of texts etc.// Swing & Event imports skipped – use Eclipse auto-completion!
public class I18NDemo { public int nrTimes = 0; // how often was the button clicked?
/** * create the I18NDemo instance * @param targetLocale the Locale used for the output */ public I18NDemo(Locale targetLocale) { // create the translator (resource file; target locale) Translator translator = new Translator("guiI18N",
targetLocale); buildGUI(translator); // create the GUI }
54
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
I18N GUI Demo – Code II
/** * builds the GUI elements with full I18N support * @param translator the Translator instance to be used */ public void buildGUI(final Translator translator) { // retrieve the GUI element builder TranslatableGUIElement guiBuilder = translator.getGenerator();
// create the window itself with an I18N title JFrame aFrame = guiBuilder.generateJFrame("guiDemo"); aFrame.getContentPane().setLayout(new BorderLayout());
// create a JMenuBar JMenuBar menuBar = new JMenuBar();
55
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
I18N GUI Demo – Code III
// generate the JMenu for this JMenu menu = guiBuilder.generateJMenu("fileMenu");
// generate a menu item with (key, useIconIfExists) JMenuItem exitItem = guiBuilder.generateJMenuItem("exitItem", true); exitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); // exit }});
// add the item to the JMenu menu.add(exitItem);
// add the menu to the menu bar and add this to the JFrame menuBar.add(menu); aFrame.setJMenuBar(menuBar);
56
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
I18N GUI Demo – Code IV
JPanel infoPanel = guiBuilder.generateBorderedJPanel("infoPanel"); aFrame.getContentPane().add(infoPanel, BorderLayout.CENTER);
// translatable JLabel JLabel label = guiBuilder.generateJLabel("clickMe"); infoPanel.add(label); // add the info button AbstractButton info = guiBuilder.generateJButton("clickButton"); info.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.err.println(translator.translateMessage("pressedN", String.valueOf(++nrTimes))); // show nr of button press } }); infoPanel.add(info); // add the info panel
57
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
I18N GUI Demo – Code V JPanel exitPanel = guiBuilder.generateBorderedJPanel("exitPanel"); aFrame.getContentPane().add(exitPanel, BorderLayout.SOUTH); AbstractButton exit = guiBuilder.generateJButton("exitButton"); // exit button exit.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { System.err.println(translator.translateMessage("bye", String.valueOf(nrTimes)); System.exit(0); // show good bye & # of pressed, exit
}}); exitPanel.add(exit); aFrame.pack(); aFrame.setVisible(true); } public static void main(String[] args) { I18NDemo demo = new I18NDemo(Locale.GERMANY); }}
58
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Ergebnis der GUI-Demo
• Hier ist das Ausgabefenster:
59
JFrameJMenuBar mit
JMenu „Datei“, Kürzel D
JMenuItem “Verlassen” mit Icon, Kürzel V, und TooltipJLabe
l JButton, Kürzel ZTooltip des
Menüeintrags
JButton, Kürzel B, mit IconUmrahmtes
JPanel
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Ergebnis der GUI-Demo
• Und hier die englische Fassung:
60
JFrameJMenuBar
mit JMenu „File“, Kürzel F
JMenuItem “Exit” mit Icon, Kürzel X, und TooltipJLabe
l JButton, Kürzel ITooltip des
Menüeintrags
JButton, Kürzel X, mit IconUmrahmtes
JPanel
Um dieses Fenster zu erhalten, ändert man eine Zeile: I18NDemo demo = new I18NDemo(Locale.US);
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Abschließende Kommentare• Sie haben es vielleicht nicht bemerkt…
– Beide Buttons, das Menü und der Menüeintrag haben ein Kürzel (mnemonic)
– Alle GUI-Elemente haben einen tool tip text• Aber die Texte etc. werden im Code nicht
angegeben!– Weil sie alle aus der Ressource-Datei stammen– Diese wird auf den folgenden Folien gezeigt
• Spielen Sie ein wenig mit der API– Sie finden Sie auf der Webseite mit Zusatzinfos– Der Source Code kann dort auch heruntergeladen
werden• Man kann die Inhalte auch “on the fly”
übersetzen– Einfach aufrufen
translator.setTranslatorLocale(newLocale)– Kann etwa über einen Menüeintrag umgeschaltet
werden
61
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Englische Ressourcedatei zur GUI Demo
hi=Hello!personalized=Hello, {0}!multi=One {0} two {1} three {2} parametersnoSuchKeyException=There is no ressource for element {0}exitPanel=Exit PanelexitButton.iconName=quit.gifexitButton.label=ExitexitButton.mnemonic=xexitButton.toolTipText=Click this button to end the democlickButton.iconName=clickButton.label=Increment counterclickButton.mnemonic=iclickButton.toolTipText=Click here to increment the counterinfoPanel=Info AreaclickMe=Click here:fileMenu.label=FilefileMenu.mnemonic=ffileMenu.toolTipText=Contains the Exit itemexitItem.iconName=quit.gifexitItem.label=ExitexitItem.mnemonic=xexitItem.toolTipText=Exits the applicationpressedTimes=The increment button was pressed {0} times.bye=Good bye - and thank you for pressing the button {0} times.guiDemo=Internationalization Demo
62
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T21
Deutsche Ressourcedatei zur GUI Demo
hi=Hallo!personalized=Hallo, {0}!multi=Eins {0} zwei {1} drei {2} ParameternoSuchKeyException=Es gibt keine Ressource f\u00fcr Eintrag {0}exitPanel=BeendenexitButton.iconName=quit.gifexitButton.label=BeendenexitButton.mnemonic=bexitButton.toolTipText=Dr\u00fccken Sie diesen Knopf zum BeendenclickButton.iconName=clickButton.label=Z\u00e4hler inkrementierenclickButton.mnemonic=zclickButton.toolTipText=Klicken Sie hier, um den Z\u00fchler zu inkrementiereninfoPanel=Info-BereichclickMe=Bitte hier klicken:fileMenu.label=DateifileMenu.mnemonic=dfileMenu.toolTipText=Enth\u0fe4lt nur den Eintrag 'Verlassen'exitItem.iconName=quit.gifexitItem.label=VerlassenexitItem.mnemonic=vexitItem.toolTipText=Beendet die AnwendungpressedTimes=Der Inkrementieren-Knopf wurde {0} Mal gedr\u00fcckt.bye=Auf Wiedersehen - und Danke, dass Sie den Knopf {0} Mal gedr\u00fcckt haben.guiDemo=Demo zur Internationalisierung
63