1 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Events Gestione degli eventi 2 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Achieving OS Independence AWT Button Swing Button Button Peer Lightweight Button Peer Motif Button OS 3 Programmazione 2 - Marco Ronchetti Modello 1.0 Fac.Scienze – Università di Trento Event is generated for a component Component gets the event Execute handleEvent HandleEvent returns true HandleEvent returns f alse Pass event to Container Ricorda: un Container è un Component! Event is consumed 4 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento handleEvent() Questo codice fa parte del sorgente di AWT public boolean handleEvent(Event evt) { switch (evt.id) { case Event.MOUSE_ENTER: return mouseEnter(evt, evt.x, evt.y); case Event.MOUSE_EXIT: return mouseExit(evt, evt.x, evt.y); case Event.MOUSE_MOVE: return mouseMove(evt, evt.x, evt.y); case Event.MOUSE_DOWN: return mouseDown(evt, evt.x, evt.y); case Event.MOUSE_DRAG: return mouseDrag(evt, evt.x, evt.y); case Event.MOUSE_UP: return mouseUp(evt, evt.x, evt.y); case Event.KEY_PRESS: case Event.KEY_ACTION: return keyDown(evt, evt.key); case Event.KEY_RELEASE: case Event.KEY_ACTION_RELEASE: return keyUp(evt, evt.key); case Event.ACTION_EVENT: return action(evt, evt.arg); case Event.GOT_FOCUS: return gotFocus(evt, evt.arg); case Event.LOST_FOCUS: return lostFocus(evt, evt.arg); } return false; } 5 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Event (1.0) /* Modifier constants */ public static final int SHIFT_MASK public static final int CTRL_MASK public static final int META_MASK ublic static final int ALT_MASK /* Action keys */ public static final int HOME ublic static final int END public static final int PGUP public static final int PAUSE public static final int INSERT /* Non-action public static public static public static public static public static keys */ final int final int final int final int final int = 1 << 0; = 1 << 1; = 1 << 2; = 1 << 3; = 1000; = 1001; = 1002;... = 1024; = 1025; ENTER BACK_SPACE TAB ESCAPE DELETE = = = = = '\n'; '\b'; '\t'; 27; 127; Questo codice fa parte del sorgente di AWT 6 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Event (1.0) Questo codice fa parte del sorgente di AWT /* Base for all window events. */ private static final int WINDOW_EVENT = 200; public static final int WINDOW_DESTROY = 1 + WINDOW_EVENT; public static final int WINDOW_EXPOSE = 2 + WINDOW_EVENT; public static final int WINDOW_ICONIFY = 3 + WINDOW_EVENT; public static final int WINDOW_DEICONIFY = 4 + WINDOW_EVENT; public static final int WINDOW_MOVED = 5 + WINDOW_EVENT; /* Base for all keyboard events. */ private static final int KEY_EVENT = 400; public static final int KEY_PRESS = 1 + KEY_EVENT; public static final int KEY_RELEASE = 2 + KEY_EVENT; public static final int KEY_ACTION = 3 + KEY_EVENT; public static final int KEY_ACTION_RELEASE = 4 + KEY_EVENT; /* Base for all mouse events. */ private static final int MOUSE_EVENT public static final int MOUSE_DOWN public static final int MOUSE_UP public static final int MOUSE_MOVE public static final int MOUSE_ENTER public static final int MOUSE_EXIT public static final int MOUSE_DRAG = = = = 500; 1 + MOUSE_EVENT; 2 + MOUSE_EVENT; 3 + MOUSE_EVENT; = 4 + MOUSE_EVENT; = 5 + MOUSE_EVENT; = 6 + MOUSE_EVENT; 7 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Event (1.0) /* Scrolling events public static final public static final public static final public static final public static final public static final public static final */ int int int int int int int private static final int SCROLL_EVENT = 600; SCROLL_LINE_UP = 1 + SCROLL_EVENT; SCROLL_LINE_DOWN = 2 + SCROLL_EVENT; SCROLL_PAGE_UP = 3 + SCROLL_EVENT; SCROLL_PAGE_DOWN = 4 + SCROLL_EVENT; SCROLL_ABSOLUTE = 5 + SCROLL_EVENT; SCROLL_BEGIN = 6 + SCROLL_EVENT; SCROLL_END = 7 + SCROLL_EVENT; /* List Events */ private static final int LIST_EVENT = 700; public static final int LIST_SELECT = 1 + LIST_EVENT; public static final int LIST_DESELECT = 2 + LIST_EVENT; Questo codice fa parte del sorgente di AWT /* Misc Event */ private static final int MISC_EVENT = 1000; //This event indicates that the user wants some action to occur public static final int ACTION_EVENT = 1 + MISC_EVENT; public static final int LOAD_FILE = 2 + MISC_EVENT; public static final int SAVE_FILE = 3 + MISC_EVENT; public static final int GOT_FOCUS = 4 + MISC_EVENT; public static final int LOST_FOCUS = 5 + MISC_EVENT; 8 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Dealing with events-1.0 import java.awt.*; import java.awt.event.*; class Applicazione extends Frame { int lastx, lasty; Graphics g; Button clear_button; public static void main(String s[]) { new Applicazione();} Applicazione() { setSize(200,200); clear_button = new Button("Clear"); add(clear_button,BorderLayout.NORTH); show(); g=getGraphics(); //dopo la show! } /** Respond to mouse clicks */ public boolean mouseDown( Event e, int x, int y) { lastx = x; lasty = y; return true; } /** Respond to mouse drags */ public boolean mouseDrag( Event e, int x, int y) { g.setColor(Color.black); g.drawLine(lastx, lasty, x, y); lastx = x; lasty = y; return true; } /** Respond to key presses */ public boolean keyDown( Event e, int key) { if ((e.id == Event.KEY_PRESS) && (key == 'c')) { clear(); return true; } else return false; } /** Respond to Button clicks */ public boolean action( Event e, Object arg) { if (e.target == clear_button) { clear(); return true; } else return false; } /** convenience method to erase the scribble */ public void clear() { g.setColor(this.getBackground()); g.fillRect(0, 0, bounds().width, bounds().height); } } 9 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Eventi 1.1 Nel modello di Java 1.0 a ciascuna componente vengono notificati gli eventi che la riguardano, ed e’ poi sua responsabilità gestirli (eventualmente scalandoli nella gerarchia di contenimento). Il modello di Java 1.1 invece “centralizza” la gestione degli eventi facendo riferimento a delle classi “Listener”, presso le quali chi genera eventi deve registrarsi. La gestione dell’evento e’ responsabilità del listener. A volte, per semplicità, e’ possibile unificare il generatore ed il gestore degli eventi. Anche in questo caso comunque si ha un vantaggio: la classe risulta chiaramente firmata come “implements Xlistener”. 10 Programmazione 2 - Marco Ronchetti Modello 1.1 Listener interface Fac.Scienze – Università di Trento Component x Container non entra in gioco AWTEvent Event is generated for a component Component has not registered for that event class Event is discarded Component has registered for that event class Component gets the event Event is consumed Component passes the Event to Listener Listener executes suitable method 11 Programmazione 2 - Marco Ronchetti multiListenerDemo Fac.Scienze – Università di Trento package listenersdemo; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class MultiListener extends JPanel implements ActionListener { JTextArea topTextArea; JTextArea bottomTextArea; JButton button1, button2; JLabel l = null; final static String newline = "\n"; public static void main(String[] args) { createAndShowGUI(); } 12 Programmazione 2 - Marco Ronchetti multiListenerDemo private static void createAndShowGUI() { Fac.Scienze – Università di Trento //Create and set up the window. JFrame frame = new JFrame("MultiListener"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create and set up the content pane. JComponent newContentPane = new MultiListener(); frame.setContentPane(newContentPane); //Display the window. frame.pack(); frame.setVisible(true); } 13 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento multiListenerDemo public MultiListener() { super(new FlowLayout()); l = new JLabel("Cosa sento io:"); add(l); topTextArea = new JTextArea(); topTextArea.setEditable(false); JScrollPane topScrollPane = new JScrollPane(topTextArea); Dimension preferredSize = new Dimension(200, 75); topScrollPane.setPreferredSize(preferredSize); add(topScrollPane); l = new JLabel("Cosa sente la spia:"); add(l); bottomTextArea = new JTextArea(); bottomTextArea.setEditable(false); 14 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento multiListenerDemo JScrollPane bottomScrollPane = new JScrollPane(bottomTextArea); bottomScrollPane.setPreferredSize(preferredSize); add(bottomScrollPane); button1 = new JButton("Fra Martino campanaro"); add(button1); button2 = new JButton("Dormi tu?"); add(button2); button1.addActionListener(this); button2.addActionListener(this); button2.addActionListener(new Spia(bottomTextArea)); setPreferredSize(new Dimension(400, 300)); } public void actionPerformed(ActionEvent e) { topTextArea.append(e.getActionCommand() + newline); topTextArea.setCaretPosition(topTextArea.getDocument().getLength()); } } 15 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento multiListenerDemo class Spia implements ActionListener { JTextArea myTextArea; public Spia(JTextArea ta) { myTextArea = ta; } public void actionPerformed(ActionEvent e) { myTextArea.append(e.getActionCommand() + MultiListener.newline); myTextArea.setCaretPosition(myTextArea.getDocument().getLength()); } } 16 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Design considerations The most important rule to keep in mind about event listeners that they should execute very quickly. Because all drawing and event-listening methods are executed in the same thread, a slow event-listener method can make the program seem unresponsive and slow to repaint itself. You might choose to implement separate classes for different kinds of event listeners. This can be an easy architecture to maintain, but many classes can also mean reduced performance. When designing your program, you might want to implement your event listeners in a class that is not public, but somewhere more hidden. A private implementation is a more secure implementation. 17 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Low-Level Events and Semantic Events Events can be divided into two groups: low-level events and semantic events. Low-level events represent window-system occurrences or low-level input. Everything else is a semantic event. Examples of low-level events include mouse and key events — both of which result directly from user input. Examples of semantic events include action and item events. Whenever possible, you should listen for semantic events rather than low-level events. That way, you can make your code as robust and portable as possible. For example, listening for action events on buttons, rather than mouse events, means that the button will react appropriately when the user tries to activate the button using a keyboard alternative or a look-andfeel-specific gesture. 18 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Listeners/Adapters public class MyClass implements MouseListener { ... someObject.addMouseListener(this); ... /* Empty method definition. */ public void mousePressed(MouseEvent e) { } /* Empty method definition. */ public void mouseReleased(MouseEvent e) { } /* Empty method definition. */ public void mouseEntered(MouseEvent e) { } /* Empty method definition. */ public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { ...//Event listener implementation goes here... } } 19 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Listeners/Adapters /* * An example of extending an adapter class instead of * directly implementing a listener interface. */ public class MyClass extends MouseAdapter { ... someObject.addMouseListener(this); ... public void mouseClicked(MouseEvent e) { ...//Event listener implementation goes here... } } 20 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Inner classes //An example of using an inner class. public class MyClass extends JFrame { ... someObject.addMouseListener( new MyAdapter()); ... class MyAdapter extends MouseAdapter { public void mouseClicked(MouseEvent e){ ...//Event listener implementation goes here... } }} 21 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Anonymous Inner classes //An example of using an inner class. public class MyClass extends JFrame { ... someObject.addMouseListener( new MouseAdapter() { public void mouseClicked(MouseEvent e){ ...//Event listener implementation goes here... } } }); ... } 22 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Inner classes An instance of InnerClass can exist only within an instance of EnclosingClass and it has direct access to the instance variables and methods of its enclosing instance. 23 Programmazione 2 - Marco Ronchetti Listeners supported by all Swing components component listener Fac.Scienze – Università di Trento Listens for changes in the component's size, position, or visibility. focus listener Listens for whether the component gained or lost the ability to receive keyboard input. key listener Listens for key presses; key events are fired only by the component that has the current keyboard focus. mouse listener Listens for mouse clicks and mouse movement into or out of the component's drawing area. mouse-motion listener Listens for changes in the cursor's position over the component. mouse-wheel listener (introduced in 1.4) Listens for mouse wheel movement over the component. 24 Programmazione 2 - Marco Ronchetti Fac.Scienze – Università di Trento Altri listeners action caret change document undoable edit item list selection window + Listeners speciali per componenti specifiche (treeNodeExpansion, ecc)