EVENTS IN JAVA (SWING)
Main Concepts:
- A Component (like a JButton) must generate an event, that is, an object that is a subclass of AWTEvent
- You must create an Event Listener that can respond when the event occurs. The event listener is specific to the type of event (different types of events will have different event listeners). The event listener is a special type of function. In it you program whatever you want to have happen when the JButton is pressed or the mouse is clicked, etc.
- You have to add the event listener to the component that generates the events. Each Component has a set of built in methods that add the various types of eventlisteners to that object: typically addXXListener() method, where XX is the event type you can listen for, for example addActionListener(). You can also remove listeners using the removeXXListener() methods.
- In order to be an event handler you have to implement the interface for the listener type, otherwise, you don't have an true event listener and it cannot be added to the component.
Changes from AWT to Swing:
Most of the main events in Swing are just the AWT events. YAY!
- AdjustmentEvent (from AWT's Scrollbar), replaced with ChangeEvent (from Swing's JSlider)
- TextEvent (from AWT's TextArea, TextField), replaced with DocumentEvent (from Swing's JTextArea, JTextField).
- These two replacements are in javax.swing.event
- Document events (and document listeners) don't seem to be that useful.
- There are a bunch of other new events in Swing, but they all seem pretty obscure. Learn them only if you need them: http://docs.oracle.com/javase/tutorial/uiswing/events/api.html
There are four ways of writing EventListeners! I'll provide examples of each:
- main class implements EventListener
* In this situation, you can only have ONE actionPerformed() method. - private inner class implements EventListener
* This seems to be the most common method - since you can create multiple independent EventListeners. - private inner class extends event Adapter (there is no adapter for ActionEvents)
* since you can only extend one class, this is an inner class rather than a main class [**no example for this one below**] - anonymous inner class
* This is harder to read and is normally only done for very simple things like Window closing
Inner classes: kind of cool and
handy. Don't overuse them. In fact, unless you have a good and specific purpose
for using an inner class, avoid them. The two places where they seem to be standard
is in event listeners and in painting programs.
Adding an Action Listener
The following pages show three ways to add an ActionListener (with comments). I'm using an ActionListener as an example of handling an event, but you can do the same with any of the other events and listeners. There is a fourth way where you extend an adapter class, but Action Events don't have adapter classes. If I have time I'll add it later.
Method 1: main class implements the EventListener
① create the GUI object that generates the action (e.g. a JButton). Make it an instance data field.
② add "implements ActionListener" to the class definition
③ write the code that handles the event in actionPerformed()
④ register the listener with the source.
public class Fire extends JFrame implements ActionListener ② { private JButton btnFire; ① public initGraphics (){ btnFire = new JButton ("* Fire *"); ① btnFire.addActionListener(this); ④ this.add (btnFire, BorderLayout.NORTH); } public void actionPerformed (ActionEvent e) ③ { if (e.getSource () == btnFire) //put all action code here { btnFire.setLabel ("Bang"); } } }
Method 2: using an Inner Class
① create the GUI object that generates the action (e.g. a JButton). Make it an instance data field (so that the inner class can access it).
② create an instance of the inner class
③ add fl as an action listener for the button.
if you have only one button you can write btnFire.addActionListener(new FireListener());
④ create the inner class. It implements ActionListener. It has the actionPerformed() method inside it.
public class Fire extends JFrame //Does not Implement ActionListener { private JButton btnFire; ① public initGraphics (){ FireListener fl = new FireListener(); ② btnFire = new JButton ("* Fire *"); ① btnFire.addActionListener(fl); ③ this.add (btnFire, BorderLayout.NORTH); } private class FireListener implements ActionListener ④ { public void actionPerformed (ActionEvent e) ④ { if (e.getSource () == btnFire) //put all action code here { btnFire.setLabel ("Bang"); } } } }
Method 3: extending an adapter (normally in an inner class)
Method 4: using an Anonymous Inner Class
① create the GUI object that generates the action (e.g. a JButton).
Make it an instance data field ← still required.
② register an action listener with the button, but ?
③ inside this, instead of naming the actionListener, create one right here
④ an anonymous inner class is created
⑤ Close off the inner class code block, then end the btnFire.addActionListener statement
public class Fire extends JFrame { private JButton btnFire; ① public initGraphics (){ btnFire = new JButton ("* Fire *"); ① this.add (btnFire, BorderLayout.NORTH); btnFire.addActionListener(new ActionListener() ② ③ { ④ public void actionPerformed (ActionEvent e) { btnFire.setLabel ("Bang"); //put all action code here } } ); ⑤ } }
Note: This ActionListener is connected ONLY to the Fire Button. If you create another button and add an action listener to it (any method), it still won't interfere with this one. It is, in fact, impossible to add this action listener to any other event source since it (the action listener) doesn't have a name.
The get/setActionCommand()
Often e.GetActionCommand()
is used instead of e.getSource()
,
e.GetActionCommand() will just return the text that is on the button.
However, you can use setActionCommand()
to change this to some other string that may be more useful.
// ... more code here ... JButton button = new JButton("Java Code Geeks - Java Examples"); // define a custom short action command for the button button.setActionCommand("Geeks"); // ... more code here ... @Override public void actionPerformed(ActionEvent e) { String action = e.getActionCommand(); if (action.equals("Geeks")) { System.out.println("Button pressed!"); } }
FYI: the getActionCommand() is a method in the ActionEvent class, but the setActionCommand() method is in the javax.swing.AbstractButton class (parent class of JButton). This class also has a version of getActionCommand() so that you can check the action command on a JButton without having to wait for an event to happen to do this.