Graphische Oberflächen – Teil 2 AWT und Swing Grundlegender Aufbau von GUIs Graphikausgabe Layoutmanagement Ereignismodell Menus und Actions GUI Elemente JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 1 Inhalt AWT und Swing • Unterschied • Einbettung von Swing in AWT Grundlegender Aufbau von Swing GUIs • Frames, Windows, Dialogs • Panels Graphikausgabe • Positionierung • paintComponent und AWT-Thread • Graphics und Ausgabeoperationen Aufbau und Positionierung • Component-Hierarchy • LayoutManagement • Spezielle Anordnungen: JTabbedPane, JSplitPane, JScrollPane, JInternalFrame, … Ereignismodell • Grundlegendes • semantische und systemnahe Ereignisse • Patterns für die Ereignisbehandlung JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 2 Inhalt (Fortsetzung) Menus und Actions GUI Elemente • • MVC-Paradigma - Abstrakte Modelle - Ereignisse Überblick über GUI Elemente - JLabel - JButton - JSpinner - JTextField - JFormattedTextField - … Dialoge (Teil 2) • Modale und Nicht-modale Dialoge • Spezielle Dialoge: JFileDialog, JOptionsPane, … Spezielle GUI-Elemente (Teil 2) • JList • JTable • JTree JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 3 Graphische Oberflächen AWT und Swing Grundlegender Aufbau von Swing GUIs Graphikausgabe Layoutmanagement Ereignismodell Menus und Actions GUI Elemente JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 4 Ereignisse Komponenten lösen Ereignisse aus • z.B. Klick auf Button, Auswahl eines Listenelements, Eingabe von Text Ereignisbehandler reagieren auf Ereignis • Implementation der entsprechenden Schnittstelle • Registration bei Komponente Ereignisobjekt liefert Zusatzinformationen • z.B. Quelle, Modifikationstasten, … public class Button extends Component { void addActionListener(ActionListener l); ... } public interface ActionListener extends EventListener { void actionPerformed(ActionEvent e); } public class ActionEvent extends AWTEvent { String getActionCommand(); int getModifiers(); String paramString(); } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 5 Hierarchie der Ereignisklassen Low-Level-Ereignisse: elementaren Nachrichten semantische Ereignisse: höherwertige Ereignisse semantische Ereignisse Low-LevelEreignisse JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 6 Hierarchie der EventListener-Interfaces JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 7 Adapterklassen Implementieren Interface mit leeren Methoden Bequeme Art, nur bestimmte Ereignisse zu behandeln Focus Adapter Key Adapter Mouse Adapter MouseMotion Adapter Window Adapter Container Component Adapter Adapter JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 8 Maus und Tastatur Ereignisse von Maus und Tastatur • z.B. Reaktion auf Mausbewegung oder Tastatureingabe • Tastenereignisse empfängt nur Komponente mit Fokus public void void void } interface KeyListener { keyPressed(KeyEvent e); keyReleased(KeyEvent e); keyTyped(KeyEvent e); public void void void void void } interface MouseListener { mouseClicked(MouseEvent e); mouseEntered(MouseEvent e); mouseExited(MouseEvent e); mousePressed(MouseEvent e); mouseReleased(MouseEvent e); public interface MouseMotionListener { void mouseDragged(MouseEvent e); void mouseMoved(MouseEvent e); } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 9 Focus-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse FocusEvent Listener-Interface FocusListener Registrierungsmethode addFocusListener Mögliche Ereignisquellen Component Ereignismethode Bedeutung focusGained Eine Komponente erhält den Focus. focusLost Eine Komponente verliert den Focus. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 10 Key-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse KeyEvent Listener-Interface KeyListener Registrierungsmethode addKeyListener Mögliche Ereignisquellen Component Ereignismethode Bedeutung keyPressed Eine Taste wurde gedrückt. keyReleased Eine Taste wurde losgelassen. keyTyped Eine Taste wurde gedrückt und wieder losgelassen. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 11 Component-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse ComponentEvent Listener-Interface ComponentListener Registrierungsmethode addComponentListener Mögliche Ereignisquellen Component Ereignismethode Bedeutung componentHidden Eine Komponente wurde unsichtbar. componentMoved Eine Komponente wurde verschoben. componentResized Die Größe einer Komponente hat sich geändert. componentShown Eine Komponente wurde sichtbar. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 12 Container-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse ContainerEvent Listener-Interface ContainerListener Registrierungsmethode addContainerListener Mögliche Ereignisquellen Container Ereignismethode Bedeutung componentAdded Eine Komponente wurde hinzugefügt. componentRemoved Eine Komponente wurde entfernt. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 13 Window-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse WindowEvent Listener-Interface WindowListener Registrierungsmethode addWindowListener Mögliche Ereignisquellen Dialog, Frame Ereignismethode Bedeutung windowActivated Das Fenster wurde aktiviert. windowClosed Das Fenster wurde geschlossen. windowClosing Das Fenster wird geschlossen. windowDeactivated Das Fenster wurde deaktiviert. windowDeiconified Das Fenster wurde wiederhergestellt. windowIconified Das Fenster wurde auf Symbolgröße verkleinert. windowOpened Das Fenster wurde geöffnet. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 14 Action-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse ActionEvent Listener-Interface ActionListener Registrierungsmethode addActionListener Mögliche Ereignisquellen Button, List, MenuItem, TextField Ereignismethode Bedeutung actionPerformed Eine Aktion wurde ausgelöst. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 15 Adjustment-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse AdjustmentEvent Listener-Interface AdjustmentListener Registrierungsmethode addAdjustmentListener Mögliche Ereignisquellen Scrollbar Ereignismethode Bedeutung adjustmentValueChanged Der Wert wurde verändert. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 16 Item-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse ItemEvent Listener-Interface ItemListener Registrierungsmethode addItemListener Mögliche Ereignisquellen Checkbox, Choice, List, CheckboxMenuItem Ereignismethode Bedeutung itemStateChanged Der Zustand hat sich verändert. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 17 Text-Ereignisse Eigenschaft Klasse, Interface oder Methode Ereignisklasse TextEvent Listener-Interface TextListener Registrierungsmethode addTextListener Mögliche Ereignisquellen TextField, TextArea Ereignismethode Bedeutung textValueChanged Der Text wurde verändert. JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 18 Entwurfsmuster für Handler-Code Die Einbindung von Handlern in die Applikation ist ein wesentliches Entwurfskriterium. Dazu gibt es unterschiedliche Ansätze, die wir besprechen wollen: • Variante 1: Implementierung eines EventListener-Interfaces • Variante 2: Lokale oder anonyme Klassen • Variante 3: Anonyme Klasse plus Handlermethode (siehe JavaBeansBeispielcode) • Variante 4: Trennung von GUI- und Anwendungscode • Variante 5: wie Variante 4 plus Datenmodell mit Change-Events JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 19 Grundlegende Überlegungen Ereignisse sollen etwas bewirken • Ausführung von Code der Applikation • Änderungen in den GUI-Elementen Gestaltung von Handler-Code ist durch zwei Herausforderungen getrieben • Zugriff auf Applikation und/oder GUI ermöglichen • gewisse Übersichtlichkeit und geeignete Strukturierung erreichen GUI auslösen einwirken Handler Applikation JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 20 Grundlegende Architektur In einer interaktiven Applikation muss es eine Klasse geben, die • Aufbau der GUI kennt • Verbindung zum Datenmodell/Applikationslogik hat GUI ? Applikation Dies ist oft das Top-Level-Fenster, d.h. eine applikationsspezifische Ableitung von JFrame oder JDialog Sind Zeichenoperationen zu implementieren, wird dies in paintComponent einer Ableitung von JPanel gemacht JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 21 Beispiel „Punkte bei Mouse-Clicks“ Applikation, in der jeder Mouse-Click als ein Punkt ausgegeben wird PointFrame • definiert Hauptfenster • hält eine Liste von Points (= Applikationsdaten) • implementiert main PointPanel • bekommt Referenz auf die Liste von Points • definiert paintComponent-Methode in der die Punkte gezeichnet werden JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 22 Beispiel „Punkte bei Mouse-Clicks“: PointFrame public class PointFrame extends JFrame { private List points; Datenmodell public PointFrame(List points) { this.points = points; setTitle("Points"); this.setContentPane(new PointPanel(this.points)); pack(); Aufbau der GUI } ... public static void main(String args[]) { List points = new ArrayList(); for (int i = 1; i <= 10; i++) points.add(new Point(i*10, i*10)); PointFrame frame = new PointFrame(points); frame.setSize(400, 300); frame.show(); } } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 23 Beispiel „Punkte bei Mouse-Clicks“: PointPanel public class PointPanel extends JPanel { List points; public PointPanel(List points) { this.points = points; } protected void paintComponent(Graphics g) { ListIterator pointsIterator = points.listIterator(); while (pointsIterator.hasNext()) { Point p = (Point) pointsIterator.next(); g.drawOval(p.x, p.y, 1, 1); } } ... } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 24 Variante 1: Implementierung EventListener-Interfaces GUI-Komponente implementiert Listener und meldet sich bei Komponente an public class PointFrame extends JFrame implements MouseListener { private List points; public PointFrame(List points) { ... getContentPane().addMouseListener(this); } public void mouseClicked(MouseEvent e) { points.add(new Point(e.getX(), e.getY())); getContentPane().repaint(); } public void mouseEntered(MouseEvent e) { ... Vorteile: • einfach Nachteil: • unhandlich wenn viele unterschiedliche Listener implementiert werden müssen, JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 25 Variante 2: Anonyme Klassen Es werden anonyme innere Klassen erzeugt, die Listener implementieren (oder Adapter erweitern) Diese greifen als innere Klassen auf die Objektvariablen zu public class PointFrame2 extends JFrame { private List points; public PointFrame2(List ps) { ... getContentPane().addMouseListener(new MouseAdapter () { public void mouseClicked(MouseEvent e) { points.add(new Point(e.getX(), e.getY())); getContentPane().repaint(); } }); } ... Vorteile: • erlaubt die Implementierung von beliebigen Listenern Nachteil: • kann auch unübersichtlich werden, weil alles in eine Klasse gepackt ist JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 26 Variante 3: Anonyme Klasse plus Handlermethode Wie bei Variante 2 anonyme innere Klassen Diese rufen aber Handler-Methoden der umgebenden Klasse auf entspricht Verfahren, wie viele GUI-Editoren Code erzeugen getContentPane().addMouseListener(new MouseAdapter () { public void mouseClicked(MouseEvent e) { mouseClickHandler(e); } }); } private void mouseClickHandler(MouseEvent e) { points.add(new Point(e.getX(), e.getY())); getContentPane().repaint(); } Vorteile: • etwas übersichtlicher JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 27 Variante 4: Trennung von GUI- und Anwendungscode Eigene Klassen, die die Listener implementieren public class MouseClickHandler implements MouseListener { private List points; public MouseClickHandler(List points) { this.points = points; } public void mouseClicked(MouseEvent e) { points.add(new Point(e.getX(), e.getY())); Component source = (Component) e.getSource(); source.repaint(); } } Zugriff auf Panel über Event-Objekt Vorteile: • Trennung von GUI-Aufbau und Ereignsbehandlung Nachteile: • In dieser Version keine strikte Trennung, weil Aufruf von repaint notwendig JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 28 Variante 5: Variante 4 + Datenmodell mit Change-Events Eigenes Datenobjekt PointList, welche die Änderungen signalisiert PointPanel5 meldet sich als Listener an und ruft bei Änderungen repaint() auf public class MouseClickHandler implements MouseListener { ... public void mouseClicked(MouseEvent e) { points.add(new Point(e.getX(), e.getY())); } } public class PointPanel5 extends JPanel implements PropertyChangeListener { ... public void propertyChange(PropertyChangeEvent evt) { repaint(); } } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 29 Variante 5: Variante 4 + Datenmodell mit Change-Events (Forts.) public class PointList { List points = new ArrayList(); PropertyChangeSupport pChSprt = new PropertyChangeSupport(this); public void add(Point p) { points.add(p); pChSprt.firePropertyChange("points", null, points); } public ListIterator listIterator() { return points.listIterator(); } public void addPropertyChangeListener(PropertyChangeListener l) { pChSprt.addPropertyChangeListener(l); } public void removePropertyChangeListener(PropertyChangeListener l) { pChSprt.removePropertyChangeListener(l); } } Vorteil: • Klare Trennung GUI – Applikation JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 30 Graphische Oberflächen AWT und Swing Grundlegender Aufbau von Swing GUIs Graphikausgabe Layoutmanagement Ereignismodell Menus und Actions GUI Elemente JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 31 Menüs mit Swing JMenuBar JMenu JMenuItem JRadioButtonMenuItem JCheckBoxMenuItem JMenu JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 32 Menüs und Untermenüs Menüleiste • Instanz von JMenuBar • Setzen mittels setJMenuBar des JFrame Menü • Instanz von JMenu (erweitert JMenuItem) • Hinzufügen zu Menüleiste oder Menü mit Methode add • Einfügen einer Trennlinie mit addSeperator Menüeintrag • Instanz von JMenuItem • Hinzufügen zu Menü mittels add • Kann Symbol und Tastenkürzel besitzen • Verfügbare Varianten: - JCheckBoxMenuItem - JRadioButtonMenuItem JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 33 Eigenschaften eines Menüeintrages Mnemonik • Unterstrichener Buchstabe für Tastaturnavigation im Menü • Setzen mit setMnemonic • Konstanten von KeyEvent für Tasten verwenden Tastenkombination • Erscheint rechts neben Menütext • KeyStroke.getKeyStroke(int keyCode, int modifiers) • Modifizierer: KeyEvent.ALT_MASK, KeyEvent.CTRL_MASK, KeyEvent.SHIFT_MASK • Setzen mittels setAccelerator Symbol • Laden von Datei mittels ImageIcon-Konstruktor • Setzen mit setIcon JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 34 Beispiel: Menüs // create and set menu bar menuBar = new JMenuBar(); setJMenuBar(menuBar); // create menu menu = new JMenu("A Menu"); menu.setMnemonic(KeyEvent.VK_A); menuBar.add(menu); // create menu item ImageIcon icon = new imageIcon("images/middle.gif"); menuItem = new JMenuItem("Both text and icon", icon); menuItem.setMnemonic(KeyEvent.VK_B); menuItem.setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_B, KeyEvent.CTRL_MASK)); menuItem.addActionListener(this); menu.add(menuItem); // add separator menu.addSeparator(); JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 35 Actions Action-Objekte realisieren Aktionen unabhängig von GUI-Elementen können an mehrere GUI-Elemente gebunden werden Klasse Action • implementiert ActionListener • hat enabled-State • unterschiedliche Werte mit getValue und putValue verwalten interface Action extends java.awt.event.ActionListener { void actionPerformed(ActionEvent e) boolean isEnabled() void setEnabled(boolean b) Object getValue(String key) void putValue(String key, Object value) void addPropertyChangeListener(PropertyChangeListener listener) void removePropertyChangeListener(PropertyChangeListener listener) } Klasse AbstractAction stellt Basisimplementierung bereit JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 36 Actions (2) Mittels getValue(String key) und putValue(String key, Object value) können Eigenschaften der Aktion verwaltet werden. • NAME: Name der Aktion • MNEMONIC_KEY: Setzen der Mnemonik • SHORT_DESCRIPTION: Benutzt für Tooltip etc. • LONG_DESCRIPTION: Zum Beispiel für kontextsensitive Hilfe • ACCELERATOR_KEY: Tastenkombination • SMALL_ICON: Ablegen eines ImageIcons • beliebige andere putValue(Action.NAME, name); putValue(Action.SMALL_ICON, icon); putValue(Action.SHORT_DESCRIPTION, "Ändern der Grundflächenfarbe in " + name.toLowerCase()); putValue("color", c); JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 37 Actions (3) Action-Objekte werden an GUI-Komponenten gebunden • an Buttons • an MenuItems • an PopupMenus • an KeyStrokes // Button add(new JButton(sampleAction)); // Menu menu.add(new MenuItem(sampleAction)); // Popup popUpMenu.add(sampleAction); // KeyStroke siehe nächste Folie JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 38 Zuordnung von KeyStrokes zu Actions Komponenten verwalten: • InputMap-Tabellen: Zuordnung von KeyStroke-Objekten zu Aktionsnamen inputMap.put(KeyStroke.getKeyStroke("ctrl S"), "panel.sample"); • ActionMap-Tabelle: Zuordnung von Aktionsnamen zu Action-Objekten ActionMap actionMap = component.getActionMap(); actionMap.put("panel.sample", sampleAction); Es gibt 3 InputMap-Tabellen (die ausgehend von der Komponente mit Fokus nacheinander untersucht werden) • WHEN-FOCUSED: verwendet, wenn Komponente Fokus hat InputMap inputMap = component.getInputMap(JComponent.WHEN_FOCUSED); • WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: verwendet, wenn eine Unterkomponente den Fokus hat InputMap inputMap = component.getInputMap(JComponent. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); • WHEN_IN_FOCUSED_WINDOW: verwendet, wenn die Komponente im selben Fenster als Komponente mit Fokus InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 39 Beispiel: ColorAction (1) Ändern die Hintergrundfarbe mit ColorActions ColorAction implementieren public class ColorAction extends AbstractAction { public ColorAction(String name, Icon icon, Color c) { putValue(Action.NAME, name); putValue(Action.SMALL_ICON, icon); putValue(Action.SHORT_DESCRIPTION, "Ändern der Grundflächenfarbe in " + name.toLowerCase()); putValue("color", c); } public void actionPerformed(ActionEvent event) { Color c = (Color) getValue("color"); setBackground(c); repaint(); } } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 40 Beispiel: ColorAction (2) Panel mit ColorButtons implementieren • Action-Objekte erzeugen class ActionPanel extends JPanel { Action yellowAction, blueAction, redAction; public ActionPanel() { yellowAction = new ColorAction("Gelb", new ImageIcon( "yellow-ball.gif"), Color.YELLOW); blueAction = new ColorAction("Blau", new ImageIcon( "blue-ball.gif"), Color.BLUE); redAction = new ColorAction("Rot", new ImageIcon( "red-ball.gif"), Color.RED); • Buttons mit Actions erzeugen und anfügen add(new JButton(yellowAction)); add(new JButton(blueAction)); add(new JButton(redAction)); JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 41 Beispiel: ColorAction (3) • KeyStrokes mit Aktionsnamen verbinden InputMap imap = getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); imap.put(KeyStroke.getKeyStroke("ctrl G"), "panel.yellow"); imap.put(KeyStroke.getKeyStroke("ctrl B"), "panel.blue"); imap.put(KeyStroke.getKeyStroke("ctrl R"), "panel.red"); • Aktionsnamen mit Action-Objekten verbinden ActionMap amap = getActionMap(); amap.put("panel.yellow", yellowAction); amap.put("panel.blue", blueAction); amap.put("panel.red", redAction); } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 42 Beispiel: ColorAction (4) PopUpMenu definieren // Kontextmenü erzeugen popUp = new JPopupMenu(); popUp.add(yellowAction); popUp.add(blueAction); popUp.add(redAction); this.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON3) popUp.show(e.getComponent(), e.getX(), e.getY()); } }); Im Frame Menu mit Actions definieren JMenuBar menuBar = new JMenuBar(); this.setJMenuBar(menuBar); JMenu bgMenu = new JMenu("Background"); menuBar.add(bgMenu); bgMenu.add(new JMenuItem(panel.yellowAction)); bgMenu.add(new JMenuItem(panel.blueAction)); bgMenu.add(new JMenuItem(panel.redAction)); JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 43 Beispiel: Actions 1/3 public class HelloAction implements Action { ... public interface Greeter { void sayHello(); public HelloAction(Greeter greeter) { } values = new HashMap(); enabled = true; propChListeners = new LinkedList(); this.greeter = greeter; } public Object getValue(String key) { return values.get(key); } public void putValue(String k, Object v) { values.put(k, v); } public void setEnabled(boolean b) { if (b != enabled) { boolean oldVal = enabled; enabled = b; firePropertyChangeEvent(new Boolean(oldVal), new Boolean(enabled)); } } ... JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 44 Beispiel: Actions 2/3 ... public boolean isEnabled() { return enabled; } public void addPropertyChangeListener(PropertyChangeListener l) { propChListeners.add(l); } public void removePropertyChangeListener( PropertyChangeListener l) { propChListeners.remove(l); } public void actionPerformed(ActionEvent e) { if (greeter != null) { greeter.sayHello(); } } private void firePropertyChangeEvent(Object oldVal, Object newVal) { ... } } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 45 Beispiel: Actions 3/3 public class ActionDemo extends JFrame implements Greeter { ... private void init() { // create action hAct = new HelloAction(this); hAct.putValue(Action.NAME, "Hello"); hAct.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_H)); hAct.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_H, KeyEvent.CTRL_MASK)); hAct.putValue(Action.SMALL_ICON, new ImageIcon("Smurf.gif")); hAct.putValue(Action.SHORT_DESCRIPTION,"Prints Hello."); ... JMenuItem helloMI = new JMenuItem("Hallo"); sayMenu.add(helloMI); helloMI.setAction(hAct); ... } public void sayHello() ... } JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 46 Zusammenfassung Applets • Kleine Programme innerhalb von Webseiten • Eingeschränkte Berechtigungen Anwendungen • Hauptfenster und Dialogfenster • Pluggable Look and Feel unter Swing Layout-Manager • Kontrollieren Position und Größe der Komponenten Ereignisse • Klick auf Schaltfläche, Texteingabe, Auswahl eines Listenelements, … • Ereignisbehandler werden bei Komponente registriert JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 47 Literatur The JavaTM Tutor, Creating a GUI with JFC/Swing (The Swing Tutorial), http://java.sun.com/docs/books/tutorial/uiswing/ Horstmann, Cornell, Core Java 2, Band 1 - Grundlagen, Markt und Technik, 2002: Kapitel 7 - 11 Krüger, Handbuch der Java-Programmierung, 3. Auflage, Addison-Wesley, 2003, http://www.javabuch.de, Kapitel 23, 24, 28, 29, 30, 35, 36 JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 48 Programmbeispiele Programmbeispiele zu den Entwurfsmuster für Handler-Code: Î Download von Homepage der LVA Î Handbuch der Java-Programmierung: Listing2801.java, Listing2802.java, Listing2803.java, Listing2804.java, Listing2805.java, Listing2806.java JOHANNES KEPLER UNIVERSITY LINZ Research and teaching network Pratikum SWE 2 © M. Löberbauer, T. Kotzmann, H. Prähofer 49