T21-GUI-de-WS0910 - Technische Universität Darmstadt

Werbung
Technische Universität Darmstadt
Telecooperation/RBG
Grundlagen der Informatik 1
Thema 21: GUI und verschachtelte Klassen
Prof. Dr. Max Mühlhäuser
Dr. Guido Rößling
Copyrighted material; for TUD student use only
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
2
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Komponenten
• Einige oft verwendete Komponenten und für
welche Interaktionsaufgaben sie verwendet
werden
• Anzeigen von Text
und Symbolen
– JLabel
• Auslösen von Aktionen
– JButton
– JMenu
– JMenuItem
Grundlagen der Informatik I: T21
3
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Komponenten
• Eingabe von Text
– JTextField
• Auswahl aus einer festen Menge von Optionen
– JCheckBox
gegenseitig ausschließend:
JRadioButton
• Auswahl aus einer variablen Menge
– JList
JComboBox
Button oder TextField +
ausklappbare Listbox
Grundlagen der Informatik I: T21
4
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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.
Grundlagen der Informatik I: T21
5
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Anatomie einer GUI-Applikation
GUI-Framework
Netz von kooperierenden
Objekten mit klar
festgelegten Zuständigkeiten:
Container
•
•
•
•
•
Komponenten
Ereignisse
Anwendungslogik
Methodenaufrufe
auf Komponente
Listener
Zustand:
wert=3
Komponenten
Container
Ereignisse
Listener
Layout
– Legt die Anordnung
der Komponenten fest
• Look & Feel
– Legt das Aussehen
der Komponenten fest
• getrennt:
Anwendungslogik
Grundlagen der Informatik I: T21
6
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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.
Faden
Programm
• Nebenläufige Programme
– Programme können mehrere Fäden besitzen.
– Mehrere Programmteile können so quasi gleichzeitig ablaufen.
Fäden
Programm
Grundlagen der Informatik I: T21
7
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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ührt
Grundlagen der Informatik I: T21
8
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Programmiermodell
Anwendung
GUI-Framework (SWING)
main
main
Komponente einfügen
AWT-EventQueue
AWT-EventQueue
Ereignis:
Komponente zeichnen
AWT-EventQueue
Ereignis:
Benutzereingabe
Grundlagen der Informatik I: T21
9
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Fenster
import 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...");
Grundlagen der Informatik I: T21
10
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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.
Grundlagen der Informatik I: T21
11
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Container
• Container und Komponenten
JFrame
JPanel
– JFrame: „top level container“
• benutzt Fenster vom Betriebssystem JLabel
– 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 aus
einer Hierarchie von Containern und Komponenten
– (Darstellung vereinfacht. Die Container zwischen JFrame
und JPanel werden hier nicht weiter betrachtet)
Grundlagen der Informatik I: T21
JFrame
...
JPanel
JLabel
12
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Komponenten
• Hinzufügen von Komponenten
JFrame
– Der JFrame erzeugt automatisch ein JPanel,
das „contentPane“.
– Darin kann die Anwendung neue
contentPane
Komponenten einfügen.
– Die Komponenten werden eingefügt, während
das Fenster noch unsichtbar ist, also zwischen
dem Erstellen des Fenster-Objekts mit new und
der Anzeige mit setVisible(true).
...
JPanel
JLabel
• JLabels
– stellen Text oder/und Symbole dar
– sind passive Komponenten, erlauben keine Interaktion
Grundlagen der Informatik I: T21
13
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Labels
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);
// ...
Grundlagen der Informatik I: T21
14
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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);
// ...
Grundlagen der Informatik I: T21
15
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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 LayoutObjekts zum Container festgelegt:
Container pane = getContentPane();
pane.setLayout(new GridLayout(ROWS, COLS));
– Die Layout-Klasse implementiert das Interface
LayoutManager.
Grundlagen der Informatik I: T21
16
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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 jeweils
maximal eine Komponente
– Die Regionen N, E, S und W werden
so klein wie möglich gehalten. Der
restliche 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 Informationen
Grundlagen der Informatik I: T21
17
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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);
}
}
...
Grundlagen der Informatik I: T21
18
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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.
Grundlagen der Informatik I: T21
19
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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.
event
source
event object
event listener
event listener
event listener
• 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)
Grundlagen der Informatik I: T21
20
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Ereignisse
import
import
import
import
import
import
import
java.awt.Container;
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.JButton;
javax.swing.JFrame;
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");
}
}
// ...
Das ist eine verschachtelte Klasse (nested class). Später mehr dazu!
}
Grundlagen der Informatik I: T21
21
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
View-Updates
• Die durch Komponenten dargestellten Informationen und ihr
Aussehen können durch Aufrufen ihrer Methoden verändert
werden.
• JLabel-API (Auszug):
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
Grundlagen der Informatik I: T21
22
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Ereignisse
import
import
import
import
import
import
import
java.awt.Container;
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.JButton;
javax.swing.JFrame;
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]");
}
}
// ...
Grundlagen der Informatik I: T21
23
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Window-Events
• Beim Klicken auf den Schließen-Button soll das
Programm nun korrekt beendet werden.
 Registrieren eines WindowListeners
• Interface WindowListener:
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
Grundlagen der Informatik I: T21
24
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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.
Grundlagen der Informatik I: T21
25
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
WindowEvents
import
import
import
import
import
import
import
java.awt.Container;
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.JButton;
javax.swing.JFrame;
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);
Grundlagen der Informatik I: T21
26
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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;
Grundlagen der Informatik I: T21
27
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
28
Option 1: Frame-Klasse implementiert
das Listener Interface direkt
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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");
}
// ...
}
Grundlagen der Informatik I: T21
29
Option 1: Frame-Klasse implementiert
das Listener Interface direkt
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
• 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
Grundlagen der Informatik I: T21
30
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Option 2: Externe Klasse implementiert
das Listener Interface
import
import
import
import
import
import
import
java.awt.Container;
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.JButton;
javax.swing.JFrame;
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]");
}
}
Grundlagen der Informatik I: T21
31
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Option 2: Externe Klasse
implementiert 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
Grundlagen der Informatik I: T21
32
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Option 2: Externe Klasse
implementiert das Listener Interface
import
import
import
import
import
import
import
java.awt.Container;
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.JButton;
javax.swing.JFrame;
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]");
}
}
Grundlagen der Informatik I: T21
33
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
34
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Verschachtelte Klassen
import
import
import
import
import
import
import
java.awt.Container;
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JLabel;
public class GUITest extends JFrame {
private JLabel infoLabel;
public GUITest(String title) {
super(title);
- Nested Class kann “private” sein
- Klasse nur innerhalb der umschließenden Klasse
sichtbar
- hat Zugriff auf private Instanzvariable der
umschließenden Klasse
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]");
}
}
//
}
...
Grundlagen der Informatik I: T21
35
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
36
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Anonyme verschachtelte Klassen
import
import
import
import
import
import
import
java.awt.Container;
java.awt.GridLayout;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
javax.swing.JButton;
javax.swing.JFrame;
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);
}
}
Grundlagen der Informatik I: T21
37
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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) { … } oder
new 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
Grundlagen der Informatik I: T21
38
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
39
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
40
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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:
Trennen Sie die Anwendungslogik
von der Präsentationslogik
Grundlagen der Informatik I: T21
41
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
42
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Model-View-Controller
Event senden
Behandelt
Nutzereingaben
Controller
controller updates
View
Anzeige
Model
A
B
C
45 35 15
Anwendungsdaten
und Verhalten
Grundlagen der Informatik I: T21
43
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
44
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
45
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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.
Grundlagen der Informatik I: T21
46
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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:
Grundlagen der Informatik I: T21
47
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
48
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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:
msg.en_US
msg.de_DE
hi=Hello!
hi=Hallo!
query=How are you today? query=Wie geht es Dir?
Grundlagen der Informatik I: T21
49
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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);
Grundlagen der Informatik I: T21
50
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
translator Package: Translator
• Übersetzen einer Nachricht über
String myTrans.translateMessage(key)
• Beispiel:
– myTrans.translateMessage("hi")  Hallo!
• Manchmal muss die Ausgabe parametrisiert werden
– Wie begrüßt man eine Person?
 “Hallo, Herr Schmidt!”
Grundlagen der Informatik I: T21
51
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Ü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…)
Grundlagen der Informatik I: T21
52
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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…
Grundlagen der Informatik I: T21
53
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
I18N GUI Demo – Code I
import translator.TranslatableGUIElement; // for GUI elements
import 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
}
Grundlagen der Informatik I: T21
54
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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();
Grundlagen der Informatik I: T21
55
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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);
Grundlagen der Informatik I: T21
56
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
57
I18N GUI Demo – Code V
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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);
}
}
Grundlagen der Informatik I: T21
58
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Ergebnis der GUI-Demo
• Hier ist das Ausgabefenster:
JFrame
JMenuItem
“Verlassen” mit
Icon, Kürzel V,
und Tooltip
JMenuBar mit
JMenu „Datei“,
Kürzel D
JLabel
JButton, Kürzel Z
Tooltip des
Menüeintrags
Umrahmtes JPanel
JButton, Kürzel B,
mit Icon
Grundlagen der Informatik I: T21
59
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Ergebnis der GUI-Demo
• Und hier die englische Fassung:
JFrame
JMenuItem
“Exit” mit Icon,
Kürzel X, und
Tooltip
JMenuBar mit
JMenu „File“,
Kürzel F
JLabel
JButton, Kürzel I
Tooltip des
Menüeintrags
Umrahmtes JPanel
JButton, Kürzel
X, mit Icon
Um dieses Fenster zu erhalten, ändert man eine Zeile:
I18NDemo demo = new I18NDemo(Locale.US);
Grundlagen der Informatik I: T21
60
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
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
Grundlagen der Informatik I: T21
61
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
©
Englische Ressourcedatei zur GUI Demo
hi=Hello!
personalized=Hello, {0}!
multi=One {0} two {1} three {2} parameters
noSuchKeyException=There is no ressource for element {0}
exitPanel=Exit Panel
exitButton.iconName=quit.gif
exitButton.label=Exit
exitButton.mnemonic=x
exitButton.toolTipText=Click this button to end the demo
clickButton.iconName=
clickButton.label=Increment counter
clickButton.mnemonic=i
clickButton.toolTipText=Click here to increment the counter
infoPanel=Info Area
clickMe=Click here:
fileMenu.label=File
fileMenu.mnemonic=f
fileMenu.toolTipText=Contains the Exit item
exitItem.iconName=quit.gif
exitItem.label=Exit
exitItem.mnemonic=x
exitItem.toolTipText=Exits the application
pressedTimes=The increment button was pressed {0} times.
bye=Good bye - and thank you for pressing the button {0} times.
guiDemo=Internationalization Demo
Grundlagen der Informatik I: T21
62
Dr. G. Rößling
Prof. Dr. M. Mühlhäuser
RBG / Telekooperation
Deutsche Ressourcedatei zur GUI Demo
©
hi=Hallo!
personalized=Hallo, {0}!
multi=Eins {0} zwei {1} drei {2} Parameter
noSuchKeyException=Es gibt keine Ressource f\u00fcr Eintrag {0}
exitPanel=Beenden
exitButton.iconName=quit.gif
exitButton.label=Beenden
exitButton.mnemonic=b
exitButton.toolTipText=Dr\u00fccken Sie diesen Knopf zum Beenden
clickButton.iconName=
clickButton.label=Z\u00e4hler inkrementieren
clickButton.mnemonic=z
clickButton.toolTipText=Klicken Sie hier, um den Z\u00fchler zu inkrementieren
infoPanel=Info-Bereich
clickMe=Bitte hier klicken:
fileMenu.label=Datei
fileMenu.mnemonic=d
fileMenu.toolTipText=Enth\u0fe4lt nur den Eintrag 'Verlassen'
exitItem.iconName=quit.gif
exitItem.label=Verlassen
exitItem.mnemonic=v
exitItem.toolTipText=Beendet die Anwendung
pressedTimes=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
Grundlagen der Informatik I: T21
63
Herunterladen