MIT AITI 2004 Swing Event Model Lecture 17
The Java Event Model In the last lecture, we learned how to construct a GUI to present information to the user. But how do GUIs interact with users? How do applications recognize when the user has done something?
package swinglab; import java.awt.*; import javax.swing.*; public class ClickReporter extends JFrame { public ClickReporter() { JButton myButton = new JButton("Click here"); Container cp = getContentPane(); cp.add(myButton); setTitle("Click Printer"); setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); show(); } public static void main(String[] args) { ClickReporter cr = new ClickReporter(); } ClickReporter
ClickPrinter Listener package swinglab; import java.awt.event.*; class ClickPrinter implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Button was pressed"); }
Adding a Listener public ClickReporter() { JButton myButton = new JButton("Click here"); ClickPrinter printer = new ClickPrinter(); click.addActionListener(printer); Container cp = getContentPane(); cp.add(myButton); setTitle("Click Printer"); setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); show(); }
ClickReporter Each time you click the button a message is displayed in a console window. Button was pressed Click here
Event Handling Diagram e.g. button, menu, text fields
Event Handling To be able to handle events in Java we need 3 things: –event sources –event objects –event listeners
Event Sources Event sources are components that can recognize user action: menus, buttons, text fields etc. Event sources have methods to add event listeners to them like addActionListener Event source reports on events and notifies all its listeners
Event Source In our ClickReporter class we create an event source, a JButton called myButton: JButton myButton = new JButton("Click here"); Click here
Event Objects Objects that represent a user action (e.g. mouse click) – contain detailed information about the event. When an event happens an event source sends an event object to its event listeners EventObject is the superclass –ActionEvent, MouseEvent, etc. are the subclasses that we use
Event Objects In our example, the event source – JButton myButton generates an event object representing a mouse click. We are not going into details of EventObjects – we will need them only as arguments to the method actionPerformed in event listeners.
Event Listeners Event listeners are objects that respond when an event occurs Any object, whose class implements the ActionListener interface, can be an event listener. If the event listener has been added to an event source, the listener will be called when an event occurs on that source.
ActionListener interface Look it up at the API in the package java.awt.event : public interface ActionListener extends EventListener { public void actionPerformed(ActionEvent e); }
Event Listener In ClickReporter class we have an event listener – ClickPrinter object called printer : ClickPrinter printer = new ClickPrinter(); and add this listener to our JButton click : click.addActionListener(printer);
create an event source: JButton myButton = new JButton("Click here"); create an event listener: ClickPrinter printer = new ClickPrinter(); add listener to the source: click.addActionListener(printer);
Add the following data fields to your ClickReporter class: private JLabel counterLabel; private int counter = 0; Add the following three lines to the ClickReporter constructor: cp.setLayout(new FlowLayout()); ClickCounter cc = new ClickCounter(this); click.addActionListener(cc);
Add these lines to your constructor: counterLabel = new JLabel( "The number of clicks is 0"); cp.add(counterLabel); Add this method to ClickReporter : void incrementCounter(){ counterLabel.setText( "The number of clicks is " + (++counter)); pack(); }
In your swinglab package create ClickCounter: package swinglab; import java.awt.event.*; class ClickCounter implements ActionListener { private ClickReporter clickReporter; ClickCounter(ClickReporter c) { clickReporter = c; } public void actionPerformed(ActionEvent e){ clickReporter.incrementCounter(); }
ClickCounter Diagram JButton ClickCounter ClickReporter actionPerformed incrementCounter Button is pressed and notifies ClickCounter ClickCounter tells ClickReporter to increment its counter
A Calculator Listener package swinglab; import java.awt.event.*; class CalcListener implements ActionListener { private Calc calculator; CalcListener(Calc c) { calculator = c; } public void actionPerformed(ActionEvent e) { calculator.calculatePressed(); }
void calculatePressed() { double n1 = Double.parseDouble(num1.getText()); double n2 = Double.parseDouble(num2.getText()); String op = (String)operation.getSelectedItem(); double ans; if (op.equals(Calc.ADD_OP)) ans = n1 + n2; else if (op.equals(Calc.SUB_OP)) ans = n1 - n2; else if (op.equals(Calc.MUL_OP)) ans = n1 * n2; else ans = n1 / n2; answerLabel.setText("Answer: " + ans); pack(); } Add this method to Calc class:
Add the Calc Listener In the Calc constructor, add an instance of CalcListener as a listener to the calculate button CalcListener cl = new CalcListener(this); calculate.addActionListener(cl);
Quiz Question 1 Q: It's annoying to make a separate class for each listener. If any class can implement an interface, can't Calc implement ActionListener and listen for the events itself? A: Yes
Quiz Question 2 Q: Is it a good idea to have Calc be a listener for itself? A: No. Calc is public, and if Calc implements ActionListener, then any outside class can use Calc to listen for unrelated events. Calc is only designed to handle Calc 's own events.
Uh oh... What happens when you type letters into the textfields and click the calculate button? Exceptions are thrown!
Exception Handling Catch those exceptions and display an error message window describing the error to the user. To show the error message window use the method JOptionPane.showMessageDialog Hint: the parentComponent should be the Calc object itself
Solution void calculatePressed() { double n1 = 0, n2 = 0; try { n1 = Double.parseDouble(num1.getText()); n2 = Double.parseDouble(num2.getText()); } catch(NumberFormatException e) { JOptionPane.showMessageDialog(this, "Must type two numbers, dummy!", "Not Numbers!", JOptionPane.ERROR_MESSAGE); } String op = (String)operation.getSelectedItem(); double ans; if (op.equals(Calc.ADD_OP)) ans = n1 + n2; else if (op.equals(Calc.SUB_OP)) ans = n1 - n2; else if (op.equals(Calc.MUL_OP)) ans = n1 * n2; else ans = n1 / n2; answerLabel.setText("Answer: " + ans); }