240 likes | 370 Views
More Event Handling. Adapters Anonymous Listeners Pop menus Validating User Input. Remember event handling. public class MyWindow extends JFrame implements ActionListener { public MyWindow (){ ... ok = new JButton ("OK"); ok.addActionListener (this); panel.add (ok); ...
E N D
More Event Handling Adapters Anonymous Listeners Pop menus Validating User Input
Remember event handling.. public class MyWindow extends JFrameimplements ActionListener{ public MyWindow(){ ... ok= new JButton("OK");ok.addActionListener(this);panel.add(ok); ... } // event handlerpublic void actionPerformed (ActionEvent e){ System.exit(0); // i.e. what happens } }
Examples… User action that results in Event Listener Type User clicks a button, presses Enter while ActionListener typing in a text field, chooses a menu item User closes a frame (main window) WindowListener User presses a mouse button while over MouseListener a Component User moves the mouse over a component MouseMotionListener Component gets the keyboard focus FocusListener Table or list selection changes ListSelectionListener Any property in a component changes, PropertyChangeListenersuch as the text on a button So when designing a GUI, you’ve got to figure out which listeners you need, for what components/user actions
ActionEvents • ActionEvents are generated from • a JButton • a JMenuItem • a JTextField (if user presses Enter) • All ActionEvents are handled by same event handler public void actionPerformed(ActionEvent e) • How to distinguish between components generating the events? • i.e. supposing have 3 buttons, 2 menu items on the same screen? Which one was clicked? • Use the event to determine which component created it getSource() method returns the object that created the event
ActionEvents • public void actionPerformed(ActionEvent e) • { • if (e.getSource() instanceof JButton) • { if (e.getSource() == saveButton) • { ………………… • } else if (e.getSource() instanceof JMenuItem) • { • if (e.getSource() == newMenuItem) • {…………… • } • else if (e.getSource() instanceof JTextField) • { • if (e.getSource() == nameTextField • {………. • } • } etc
ActionEvents • public void actionPerformed(ActionEvent e){ • if (e.getSource() instanceof JButton) { if (e.getSource() == saveButton) {… • } else if (e.getSource() instanceof JMenuItem) { • if (e.getSource() == newMenuItem){… • } • else if (e.getSource() instanceof JTextField){ • if (e.getSource() == nameTextField{… • } • } public class MyWindow extends JFrame { private JButton saveButton; private JMenuItem newMenuItem; private JTextField nameTextField; public MyWindow(){ … … Components that the user will interact can be set up as instance variables of the class. Then Can access in the action performed Method. More on code structure later..
Adapters • Certain events can be generated by multiple actions, • e.g. opening, closing, minimising, maximising, activating, deactivating a window all create a WindowEvent • e.g. clicking a mouse, moving a mouse over a component, pressing and releasing the mouse buttons all create a MouseEvent • the Listener has to handle all actions • many event handlers, one for each type of event (because different things happen as a response to each event…)
Listeners with multiple event handlers • MouseListener: • mouseClicked(MouseEvent e) • mouseEntered(MouseEvent e) • mouseExited(MouseEvent e) • mousePressed(MouseEvent e) • mouseReleased(MouseEvent e) • Your window may only need to handle one event but as it implements a listener interface it must override all event handler methods..! • That’s the rule of implementing interfaces…. • WindowListener: • windowActivated(WindowEvent e) • windowClosed(WindowEvent e) • windowClosing(WindowEvent e) • windowDeactivated(WindowEvent e) • windowDeiconified(WindowEvent e) • windowIconified(WindowEvent e) • windowOpened(WindowEvent e) • MouseMotionListener: • mouseMoved(MouseMotionEvent e) • mouseDragged(MouseMotionEvent e)
public class MyWindow extends JFrame implements WindowListener{ //instance variables //constructor • //createContentPane • //createMenubar • //event handlers • public void windowActivated(WindowEvent e){} // do nothing • public void windowClosed(WindowEvent e){ • } // do nothing • windowClosing(WindowEvent e){ • //include code here} • windowDeactivated(WindowEvent e){} //do nothing • windowDeiconified(WindowEvent e){} // do nothing • windowIconified(WindowEvent e){} // do nothing • windowOpened(WindowEvent e){ • } // do nothing} All I want to do is respond to closing a window….
Adapters • To facilitate this: • an abstract Adapter class is created which implements empty methods for all event handlers • each xxxListener interface has an associated xxxAdapter class • E.g. WindowListener has the WindowsAdapter class • the Listener class then becomes a subclass of the Adapter class and overrides only the event handlers of interest • Think of the adapter class as implementing a set of dummy methods to save you work..
Using Adapters // create WindowListener class class MyWindowListener extends WindowAdapter { // override event handler public void windowClosing(WindowEvent e) { // include logic here } } ... // register window listener with the frame// within the frame’s constructor this.addWindowListener(new MyWindowListener()); ...
What if you adapter class can’t be used? • To use an adapter class, your class has to inherit from it • Since java supports single inheritance, can be restrictive – • A solution is to use an anonymous listener… • But be aware of performance issues – using anonymous listeners, you’re loading an extra class – increases start up time and memory requirements
Anonymous Listeners • Listeners can be defined anonymous (i.e. with no name) • Class is created “on the fly” (i.e. placed where it is needed, where the listener is registered with the component) • anonymous cannot be used by another component • responsible for only a single component no need to include getSource() etc to identify where the event was generated • Used frequently with WindowListeners.. Why do you think? • Syntax is component.addXXXListener( [whole definition of XXXListener goes here] );
Anonymous Listener Example addWindowListener( //begin implementation of Listener new WindowAdapter() { // begin implementation of required method public void windowClosing(WindowEvent e){ // include cleanup code here } // end required method } end Listener); // end addWindowListener Adapter class is instantiated. No name… ..and relevant method that you want your i/f to respond to is called
PopupMenus • Pop-up menus are free floating menus that are associated with an underlying component (the invoker) • E.g. right clicking on your mouse as you read this… • How would you implement..? Create a menu, decide what makes it appear (e.g. mouse right click ? .. so listen for this and show the menu), say exactly where on screen it should pop up, what events happen when I select menu options, etc.
PopupMenus • Brought into existence by a pop-up trigger event that occurs while the mouse is over the invoker • trigger event is platform dependent • normally a MouseEvent • could be mouse pressed or mouse released event • Pop-up menu created using JPopupMenu class • JMenuItems and separators added as before • Pop-up menu is displayed using show() • void show(Component origin, int x, int y) what component is associated with the it, and the location to display it…
Using Popup Menus • Create the component – the popup menu • Register listeners with the menu items so you know when user has clicked on them • Add event handling for menu items of the popup menu • Create a MouseListener (using MouseAdapter) to listen for the trigger (user right click) • Add event handling code to display the popup when requested • Register MouseListener with appropriate component (normally some container)
Create Popup Menu private JPopupMenu createPopUp(){ // create pop-up menu JPopupMenu popup = new JPopupMenu(); // add menu items and associated listener menuItem = new JMenuItem(“whatever…”); menuItem.addActionListener(myActionListener); popup.add(menuItem); return popup;} Invoke this method in the JFrame constructor to create the popup menu
Create MouseListener that triggers the pop up menu Note that we’re using an adapter class // create PopupListener (a MouseListener) class PopupListener extends MouseAdapter{ JPopupMenu popup; // instance variable PopupListener(JPopupMenu popup){ this.popup = popup; } // include appropriate event handlers // for relevant acions e.g. mousePressed public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { popup.show(e.getComponent(), e.getX(), e.getY()); } } }
Register MouseListener • Instantiate Listener • Register listener with the component that popup is invoked on myPopupListener = new PopupListener(popup); invoker.addMouseListener(myPopupListener); e.g. the invoker might be a panel..
Validating User Input • In GUI user enters text into JTextFields • Use String getText() to extract text from field • May need to extract numbers from returned String • Use Envelop classes – wrapper classes for each primitive datatype • Integer int int Integer.parseInt(String s) • Double double double Double.parseDouble(String s) • Float floatfloat Float.parseFloat(String s) • Must handle the NumberFormatException
Validating User Input public void actionPerformed (ActionEvent e){ // extract string from textfieldString str = field.getText().trim(); try{ // try to extract num from string double num = Double.parseDouble(str); // successfully extracted the number // do something with it... } // unsuccessful extract so handle the error catch (NumberFormatException e){ // display error msgJOptionPane.showMessageDialog(null,"You did not enter a number"); } } An example… Trim() moethod gets rid of leading and trailing whitespaces..
Looked at… • Implementing listeners • E..g MouseListener, WindowListener • As interfaces (just implement in your frame) • As adapter classes (when there are many method you don’t need) • As anonymous listeners – when inheriting from adapter class not good.. • Creating Pop Menus • Example of validating user input • Remember that field text is extracted as a String – convert if needs to be treated as a number…