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