import javax.swing.JLabel

Werbung
Grundzüge der Informatik 1
Teil 5: Benutzeroberflächen
5.2 Einführung GUI-Programmierung
Prof. Dr. Max Mühlhäuser
FG Telekooperation
TU Darmstadt
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
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
2
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
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
3
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
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
4
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.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
5
GUI-Framework
Anatomie einer
GUI-Applikation
Container
Komponenten
Ereignisse
Anwendungslogik
Methodenaufrufe
auf Komponente
Listener
Zustand:
wert=3
2003 © MM ...
Netz von kooperierenden
Objekten mit klar
festgelegten
Zuständigkeiten:
• Komponenten
• Container
• Ereignisse
• Listener
• Layout
– Legt die Anordnung
der Komponenten fest
• Look & Feel
– Legt das Aussehen
der Komponenten fest
• getrennt:
Anwendungslogik
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
6
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
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
7
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 (incl. 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.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
8
Programmiermodell
Anwendung
GUI-Framework (SWING)
main
main
Komponente einfügen
AWT-EventQueue
AWT-EventQueue
Ereignis:
Komponente zeichnen
AWT-EventQueue
Ereignis:
Benutzereingabe
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
9
Fenster
import javax.swing.JFrame;
public class GUITest extends JFrame {
// The height of the window in pixels
public static final int WIDTH = 400;
// The width 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);
}
// Starts the 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.show();
System.out.println("Exiting main...");
}
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
10
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.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
11
Container
JFrame
• Container und Komponenten JPanel
– JFrame: „top level container“
JLabel
• 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 aus
einer Hierarchie von Containern und Komponenten
–
(Darstellung vereinfacht. Die Container zwischen JFrame und
JPanel werden hier nicht weiter betrachtet)
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
JFrame
...
JPanel
JLabel
12
Komponenten
• Hinzufügen von Komponenten
– Der JFrame erzeugt automatisch ein JPanel,
das „contentPane“.
contentPane
– Darin kann die Anwendung neue
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
dem Öffnen mit show().
JFrame
...
JPanel
JLabel
• JLabels
– stellen Text oder/und Symbole dar
– sind passive Komponenten, erlauben keine Interaktion
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
13
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);
}
...
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
14
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);
}
...
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
15
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ünsche Layout wird durch zuordnen eines LayoutObjekts zum Container festgelegt:
Container pane = getContentPane();
pane.setLayout(new GridLayout(ROWS, COLS));
– Die Layout-Klasse implementiert das Interface
LayoutManager.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
16
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, ...
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
17
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);
}
...
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
18
Ereignisse (Events)
• Jedesmal, wenn der Benutzer eine Taste drückt oder die Maus
bewegt, tritt ein Ereignis auf.
• 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.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
19
Listener
• Mehrere Listener können sich bei einer Ereignis-Quelle (event
source) registieren 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 EreignisQuelle. Z.B. mittels addActionListener
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
20
Ereignisse
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 {
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");
}
}
...
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
21
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
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
22
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]");
}
}
...
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
23
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
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
24
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.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
25
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);
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
26
WindowEvents
// 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.show();
}
public static final int WIDTH = 400;
public static final int HEIGHT = 300;
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
27
Zusammenfassung
Bisher betrachtet:
Client-Seite
• Erzeugen von
Komponenten und
Layout
• Implementieren von
Listenern =
Ereignis-Senken
Im folgenden:
Komponenten-Seite
• Programmieren eigener
Komponenten
• Implementieren von
Ereignis-Quellen und
erzeugen von Events
• Darstellung von
Komponenten
(zeichnen)
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
28
Eigene Komponenten
• Darstellung von Komponenten
– Die Darstellung jeder Komponente ist letztendlich durch
eine Reihe von Zeichenbefehlen realisiert.
– Eine Komponente muss neu gezeichnet werden, wenn eines
der folgenden Ereignisse eintritt:
• Die Komponente wurde eben geöffnet oder war durch ein
darrüberliegendes Objekt verdeckt und ist jetzt wieder
sichtbar.
ØDas Neuzeichnen wird durch das Framework
angefordert.
• Ein Zustand der Komponente, die sich auf ihr Erscheinungsbild
auswirkt, hat sich verändert.
ØDas Neuzeichnen wird explizit z.B. in einer SetMethode der Komponente angefordert.
– Diese Vorgehensweise wird oft als Damage/Repair-Prinzip
bezeichnet.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
29
Zeichnen
• Das Framework initiiert das Neuzeichnen einer Komponente durch
den Aufruf ihrer Methode paintComponent().
import
import
import
import
java.awt.Graphics;
java.awt.Color;
java.awt.FontMetrics;
javax.swing.JComponent;
class MyButton extends JComponent {
// The text displayed on the button
private String text = "Button";
/**
* Paints the component.
* @param g the Graphics context in which to paint
*/
public void paintComponent(Graphics g) {
System.out.println("SWING requests a repaint");
}
}
• Im Grunde handelt es sich hierbei wieder um Ereignisverarbeitung.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
30
Graphics
• Das Graphics-Objekt
– enthält Zustand (=Kontext)
•
•
•
•
aktuelle Zeichenfläche (Bildschirmbereich)
aktuelle Zeichenfarbe
aktuelle Schrift
...
– stellt Methoden zum Zeichnen bereit
public void paintComponent(Graphics g) {
// Set painting color to lightGray
g.setColor(Color.lightGray);
// Draw rectangle with a 3D-style raised border
g.fill3DRect(0, 0, getWidth(), getHeight(), true);
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
31
Text
• Darstellen von Text
// Set painting color to black
g.setColor(Color.black);
// Draw text at coordinates (20, 20)
g.drawString(text, 20, 20);
}
• Zentrieren von Text
– Ein FontMetrics-Objekt kapselt die Eigenschaften und
Zeichengrößen einer Schriftart.
height
p
ascent
descent
Ursprung
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
32
Zeichnen
public void paintComponent(Graphics g) {
// Set the fill color to lightGray and draw a 3D button with raised border
g.setColor(Color.lightGray);
g.fill3DRect(0, 0, getWidth(), getHeight(), true);
// The FontMetrics object provided by getFontMetrics encapsulates
// information about the rendering of the current font on the current screen
FontMetrics fm = g.getFontMetrics();
// Set text color to black
g.setColor(Color.black);
// Draw text centered on the button
g.drawString(
text,
(getWidth()-fm.stringWidth(text))/2,
(getHeight()-fm.getHeight())/2+fm.getAscent());
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
33
Maus-Ereignisse
• interface java.awt.event.MouseListener:
void mouseEntered(MouseEvent e)
Der Mauszeiger hat die Komponente
„betreten“
void mouseExited(MouseEvent e)
Der Mauszeiger hat die Komponente
verlassen
void mousePressed(MouseEvent e)
Eine Maustaste wurde über der
Komponente gedrückt
void mouseReleased(MouseEvent e) Eine Maustaste wurde losgelassen
void mouseClicked(MouseEvent e)
2003 © MM ...
Eine Maustaste wurde gedrückt und an der
gleichen Stelle wieder losgelassen
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
34
Maus-Ereignisse
• Zustände eines Buttons
– p (pressed): Maustaste wurde über dem Button
niedergedrückt und wird gehalten
– r (recessed): Der Button wird vertieft dargestellt
• Zustandsdiagramm:
mouseReleased
mousePressed
p=0
r=0
mouseExited
p=1
r=1
mouseReleased
2003 © MM ...
p=1
r=0
mouseEntered
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
35
Maus-Ereignisse
class MyButton extends JComponent implements MouseListener {
...
// Invoked when the mouse enters a component
public void mouseEntered(MouseEvent e) {
if (pressed) {
recessed = true;
repaint();
}
}
// Invoked when the mouse exits a component
public void mouseExited(MouseEvent e) {
if (pressed) {
recessed = false;
repaint();
}
}
// Invoked when a mouse button has been pressed on a component
public void mousePressed(MouseEvent e)
pressed = recessed = true;
repaint();
}
// Invoked when a mouse button has been released on a component
public void mouseReleased(MouseEvent e) {
pressed = recessed = false;
repaint();
}
public void mouseClicked(MouseEvent e) {
}
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
36
Ereignis-Quellen
• Verwaltung der Listener
– Die Klasse EventListenerList verwaltet eine Liste von
Tupeln (Klasse des Listener-Interface, Objektreferenz)
– Unsere Komponente kann die Verwaltung delegieren:
/**
* List of listeners interested in events generated by this compo nent.
* We delegate bookkeeping of event listeners to EventListenerList.
*/
private EventListenerList listenerList = new EventListenerList();
/**
* Adds an <code>ActionListener</code> to the button.
* @param l the <code>ActionListener</code> to be added.
*/
public void addActionListener(ActionListener l) {
listenerList.add(ActionListener.class, l);
}
/**
* Removes an <code>ActionListener</code> from the button.
* @param l the listener to be removed.
*/
public void removeActionListener(ActionListener l) {
listenerList.remove(ActionListener.class, l);
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
37
Ereignis-Quellen
/**
* Fires an <code>ActionEvent</code>.
*/
private void fireActionEvent() {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Create the event object
ActionEvent actionEvent = new ActionEvent(
this, ActionEvent.ACTION_PERFORMED, "click");
// Notify the listeners
for (int i=0; i<listeners.length; i+=2)
((ActionListener)listeners[i+1]).actionPerformed(actionEvent);
}
• Senden von Events an die Listener
– Das von listenerList.getListenerList() gelieferte Array enthält
alternierend Klassen-Objekte und Listener-Objekte.
– Die Klassen-Objekte beschreiben die Art des Ereignisses, für das sich
der Listener interessiert. (z.B.: ActionListener.class)
– Das Listener-Objekt ist der Empfänger des Ereignisses.
– Eine einzelne ListenerList kann verwendet werden, um
unterschiedliche Listener-Typen zu verwalten. In diesem Fall muss ein
entsprechender Typtest im Schleifenrumpf hinzugefügt werden.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
38
Ereignis-Quellen
• Auslösen des Ereignisses:
mouseReleased
mousePressed
p=0
r=0
mouseExited
p=1
r=1
mouseReleased
:actionPerformed
p=1
r=0
mouseEntered
/**
* Invoked when a mouse button has been released on a component.
*/
public void mouseReleased(MouseEvent e) {
if (recessed) {
fireActionEvent();
repaint();
}
pressed = recessed = false;
}
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
39
Eigene Komponenten:
Zusammenfassung
• Zeichnen: Damage/Repair-Prinzip
– Zeichenmethoden sollten nur im Kontext von
paintComponent() ausgeführt werden.
– repaint() zeichnet nicht unmittelbar, sondern es fordert
das Neuzeichnen der Komponente an.
– Das Framework ruft daraufhin paintComponent() vom
Event-Dispatch-Thread aus auf und zeichnet bei Bedarf
auch andere Komponenten neu. (z.B.: Rahmen,
transparente Objekte)
• Ereignis-Quellen
– Die Verwaltung der Listener kann an EventListenerList
delegiert werden.
2003 © MM ...
GdI1 - Teil 5.2: Graphische Benutzeroberflächen
40
Herunterladen