Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 1
Chapter 17
How to handle events and validate data
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 2
Objectives
Applied
Given a class that extends JPanel and includes one or more components that generate events, modify the class so that it implements the appropriate listener interface to respond to those events.
Given a class that extends JPanel and includes one or more components that generate events, create a separate class to handle those events, and modify the panel class so that it adds the event class as a listener for each event source.
Given a class that extends JPanel and includes one or more components that generate events, add an inner class to handle the events.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 3
Objectives (continued) Given a class that extends JPanel and includes one or more
components that generate events, add anonymous inner classes to handle the events.
Given a class that extends JPanel and includes one or more components that generate events, add event listeners to handle keyboard and focus events.
Write statements that display message dialogs using the JOptionPane class.
Given a class that extends JPanel and includes one or more text field components, add data validation to the event listeners for the panel.
Given the requirements for an application that uses the event handling and data validation techniques presented in this chapter, write the code to implement the application.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 4
Objectives (continued) Knowledge
Distinguish among an event, an event source, and an event listener.
Explain the difference between semantic events and low-level events.
List four options for structuring the classes that implement the listener interface for an event.
List two options for structuring the classes to handle multiple event sources for a particular event.
Explain the difference between an inner class and an anonymous inner class.
Describe at least two situations in which you would want to listen to low-level events.
Explain the benefit of using adapter classes rather than implementing listener interfaces.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 5
What happens when a button is pressed
JButton ActionListenerActionEvent
What happens when any event occurs
event source event listenerevent object
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 6
The Java event model GUI applications depend on events that represent user interactions
such as clicking a button or selecting an item from a list.
All events are represented by an event object that derives from the EventObject class. The event object contains information about the event that occurred.
An event listener is an object that responds to an event.
The class that defines an event listener must implement an event listener interface.
A component that generates an event is called an event source.
To respond to an event, an application must register an event listener object with the event source that generates the event.
The class for the event source provides a method for registering event listeners. Then, when the event occurs, the event source creates an event object and passes it to the event listener.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 7
Semantic events
Action Event object Listener interface
Button clicked ActionEvent ActionListener
Combo box item selected ActionEvent ItemEvent
ActionListener ItemListener
List item selected ListSelectionEvent ListSelectionListener
Text component changed DocumentEvent DocumentListener
Radio button selected ActionEvent ItemEvent
ActionListener ItemListener
Check box selected ActionEvent ItemEvent
ActionListener ItemListener
Scroll bar repositioned AdjustmentEvent AdjustmentListener
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 8
Low-level events
Action Event object Listener interface
Window changed WindowEvent WindowListener
Focus changed FocusEvent FocusListener
Key pressed KeyEvent KeyListener
Mouse moved or clicked MouseEvent MouseListener
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 9
The two types of Java events Two types of events exist in Java: semantic events and low-level
events.
A semantic event is related to a specific component such as clicking a button or selecting an item from a list.
Low-level events are less specific, like clicking a mouse button, pressing a key on the keyboard, or closing a window.
Most events and listeners are stored in the java.awt.event package, but some of the newer events and listeners are stored in the javax.swing.event package.
Some user actions create more than one event. You can use listeners to respond to any of them.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 10
Two steps to handle any event 1. Create a class that implements the appropriate listener interface. In
this class, you must code an implementation of the appropriate listener interface method to respond to the event.
2. Register an instance of the listener class to the event source by calling the appropriate addeventListener method
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 11
Four options for implementing the listener interface Implement it in the panel itself
Implement it in a separate class
Implement it in an inner class within the panel
Implement it in an anonymous inner class
Two options for handling multiple event sources Create one listener that handles all events for the panel
Create a separate listener for each event
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 12
Code for a panel that implements the ActionListener interface
class FutureValuePanel extends JPanel implements ActionListener { private JButton calculateButton; private JButton exitButton; public FutureValuePanel() { calculateButton = new JButton("Calculate"); calculateButton.addActionListener(this); this.add(calculateButton); exitButton = new JButton("Exit"); exitButton.addActionListener(this); this.add(exitButton); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 13
Code for a panel that implements the ActionListener interface (continued)
public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == exitButton) System.exit(0); else if (source == calculateButton) calculateButton.setText("Clicked!"); } }
Notes The easiest way to implement a listener interface is in the class
that defines the panel or frame that contains the components that generate the events.
When the panel or frame class itself implements the listener, you can specify the this keyword as the parameter to the method that registers the listener.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 14
Code for a panel that uses a separate listener class: The panel class class FutureValuePanel extends JPanel { public JButton calculateButton; public JButton exitButton; public FutureValuePanel() { ActionListener listener = new FutureValueActionListener(this); calculateButton = new JButton("Calculate"); calculateButton.addActionListener(listener); this.add(calculateButton); exitButton = new JButton("Exit"); exitButton.addActionListener(listener); this.add(exitButton); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 15
Code for a panel that uses a separate listener class: The listener class class FutureValueActionListener implements ActionListener { private FutureValuePanel panel; public FutureValueActionListener(FutureValuePanel p) { this.panel = p; } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == panel.exitButton) System.exit(0); else if (source == panel.calculateButton) panel.calculateButton.setText("Clicked!"); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 16
How to implement an event listener as a separate class If you implement a listener as a separate class, you’ll need to
provide a way for the listener class to access the source components and any other panel components that are required to respond to the event.
One way to do that is to pass the panel to the constructor of the listener class and declare the components that need to be referred to as public.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 17
How to implement an event listener as an inner class An inner class is a class that is contained within another class.
An inner class has access to all of the members of its containing class. Because of that, inner classes are often used to implement event listeners.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 18
Code that implements the listener as an inner class class FutureValuePanel extends JPanel { private JButton calculateButton; private JButton exitButton; public FutureValuePanel() { ActionListener listener = new FutureValueActionListener(); calculateButton = new JButton("Calculate"); calculateButton.addActionListener(listener); this.add(calculateButton); exitButton = new JButton("Exit"); exitButton.addActionListener(listener); this.add(exitButton); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 19
Code that implements the listener as an inner class (continued) class FutureValueActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == exitButton) System.exit(0); else if (source == calculateButton) calculateButton.setText("Clicked!"); } } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 20
How to implement separate event listeners for each event You can eliminate the code in the event listener class that
determines the event source by creating a separate listener class for each component that raises the event.
In that case, you simply register an instance of each event listener class with the appropriate event source.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 21
Code that implements separate listeners for each event class FutureValuePanel extends JPanel { private JButton calculateButton; private JButton exitButton; public FutureValuePanel() { calculateButton = new JButton("Calculate"); calculateButton.addActionListener( new CalculateListener()); this.add(calculateButton); exitButton = new JButton("Exit"); exitButton.addActionListener(new ExitListener()); this.add(exitButton); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 22
Code that implements separate listeners for each event (continued) class CalculateListener implements ActionListener { public void actionPerformed(ActionEvent e) { calculateButton.setText("Clicked!"); } } class ExitListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.exit(0); } } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 23
The syntax for creating an anonymous class for an event listener
new ListenerInterface() { class-body }
How to implement event listeners as anonymous inner classes An anonymous inner class is a class that is both declared and
instantiated in one statement.
Anonymous inner classes are often used as event listeners.
Anonymous inner classes force you to mix the code that creates a panel with the code that responds to the panel’s events. So they should be used for only the simplest event listeners.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 24
Code that implements event listeners as anonymous classes class FutureValuePanel extends JPanel { private JButton calculateButton; private JButton exitButton; public FutureValuePanel() { calculateButton = new JButton("Calculate"); calculateButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { calculateButton.setText("Clicked!"); } } ); this.add(calculateButton);
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 25
Code that implements event listeners as anonymous classes (continued) exitButton = new JButton("Exit"); exitButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } } ); this.add(exitButton); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 26
Common low-level events and listeners Event Interface Methods
Moving the focus
FocusListener void focusLost(FocusEvent e) void focusLost(FocusEvent e)
Pressing or releasing a key
KeyListener void keyPressed(KeyEvent e) void keyReleased(KeyEvent e) void keyTyped(KeyEvent e)
Moving or dragging the mouse
MouseMotionListener void mouseDragged(MouseEvent e) void mouseMoved(MouseEvent e)
Clicking the mouse
MouseListener void mouseClicked(MouseEvent e) void mouseEntered(MouseEvent e) void mouseExited(MouseEvent e) void mousePressed(MouseEvent e) void mouseReleased(MouseEvent e)
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 27
Common low-level events and listeners (continued) Event Interface Methods
Moving or sizing a component
ComponentListener void componentHidden(ComponentEvent e) void componentMoved(ComponentEvent e) void componentResized(ComponentEvent e) void componentShown(ComponentEvent e)
Working with the window
WindowListener void windowActivated(WindowEvent e) void windowClosed(WindowEvent e) void windowClosing(WindowEvent e) void windowDeactivated(WindowEvent e) void windowDeiconified(WindowEvent e) void windowIconified(WindowEvent e) void windowOpened(WindowEvent e)
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 28
Methods that add low-level listeners
Event source Method
Component addFocusListener(FocusListener)
Component addKeyListener(KeyListener)
Component addMouseMotionListener(MouseMotionListener)
Component addMouseListener(MouseListener)
Component addComponentListener(ComponentListener)
Window addWindowListener(WindowListener)
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 29
How to work with focus events A focus event occurs when the focus moves to or from a component.
To implement a focus listener, you must implement both of the methods of the FocusListener interface.
Methods of the FocusListener interface
Method Description void focusGained( FocusEvent e)
Invoked when a component that implements a focus listener gains the focus.
void focusLost( FocusEvent e)
Invoked when a component that implements a focus listener loses the focus.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 30
Common methods of the FocusEvent class
Method Description
getComponent() Returns the component where the event occurred.
isTemporary() Returns true if the focus is a temporary change.
getOppositeComponent() Returns the other component involved in the focus change. Introduced with JDK 1.4.
A method of the JTextComponent class
Method Description
selectAll() Selects all of the text in the text component.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 31
A class that implements the FocusListener interface
public class AutoSelect implements FocusListener { public void focusGained(FocusEvent e) { if (e.getComponent() instanceof JTextField) { JTextField t = (JTextField) e.getComponent(); t.selectAll(); } } public void focusLost(FocusEvent e) {} }
A text field that uses the focus listener paymentTextField = new JTextField(10); paymentTextField.addFocusListener(new AutoSelect()); displayPanel.add(paymentTextField);
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 32
How to work with keyboard events A keyboard event occurs when a user presses, releases, or presses
and releases a key.
The KeyEvent class inherits the InputEvent class.
Methods of the KeyListener interface
Method Description
void keyPressed(KeyEvent e) Invoked when a key is pressed.
void keyReleased(KeyEvent e) Invoked when a key is released.
void keyTyped(KeyEvent e) Invoked when a key is pressed and released.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 33
Common methods of the KeyEvent class
Method Description
getKeyCode() Returns an int code that represents the key pressed.
getKeyChar() Returns a char that represents the key pressed.
isControlDown() Returns a boolean that indicates if the Ctrl key is down.
isAltDown() Returns a boolean that indicates if the Alt key is down.
isShiftDown() Returns a boolean that indicates if the Shift key is down.
A method of the InputEvent class
Method Description
consume() Stops further processing of the event.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 34
A class that implements the KeyListener interface public class NumFilter implements KeyListener { public void keyTyped(KeyEvent e) { char c = e.getKeyChar(); if ( c != '0' && c != '1' && c != '2' && c != '3' && c != '4' && c != '5' && c != '6' && c != '7' && c != '8' && c != '9' && c != '.' && c != '+' && c != '-') e.consume(); } public void keyPressed(KeyEvent e) {} public void keyReleased(KeyEvent e) {} }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 35
A text field that uses the key listener paymentTextField = new JTextField(10); paymentTextField.addKeyListener(new NumFilter()); displayPanel.add(paymentTextField);
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 36
How to work with adapter classes An adapter class is a class that implements all the methods of a
listener interface as empty methods. Then, an event listener class that inherits an adapter class must override only the methods that the program needs.
Common adapter classes
Class Interface
WindowAdapter WindowListener
FocusAdapter FocusListener
KeyAdapter KeyListener
MouseAdapter MouseListener
MouseMotionAdapter MouseMotionListener
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 37
The AutoSelect class using FocusAdapter public class AutoSelect extends FocusAdapter { public void focusGained(FocusEvent e) { if (e.getComponent() instanceof JTextField) { JTextField t = (JTextField) e.getComponent(); t.selectAll(); } } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 38
The NumFilter class using KeyAdapter public class NumFilter extends KeyAdapter { public void keyTyped(KeyEvent e) { char c = e.getKeyChar(); if ( c != '0' && c != '1' && c != '2' && c != '3' && c != '4' && c != '5' && c != '6' && c != '7' && c != '8' && c != '9' && c != '.' && c != '+' && c != '-') e.consume(); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 39
An error message displayed in a JOptionPane dialog box
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 40
The showMessageDialog method of the JOptionPane class
Syntax showMessageDialog(parentComponent, messageString, titleString, messageTypeInt);
Arguments
Argument Description
parentComponent An object representing the component that’s the parent of the dialog box.
messageString A string representing the message to be displayed in the dialog box.
titleString A string representing the title of the dialog box.
messageTypeInt An int that indicates the type of icon that will be used for the dialog box.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 41
Fields used for the message type parameter
Icon displayed Field
(none) PLAIN_MESSAGE
INFORMATION_MESSAGE
WARNING_MESSAGE
ERROR_MESSAGE
QUESTION_MESSAGE
How to display error messages The showMessageDialog method is a static method of the
JOptionPane class that is commonly used to display dialog boxes with error messages for data validation.
You can also use the JOptionPane class to accept input from the user.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 42
Code that displays the Invalid Entry dialog box String message = "Monthly Investment is a required field.\n" + "Please re-enter."; JOptionPane.showMessageDialog(this, // assumes "this" is a component message, "Invalid Entry", JOptionPane.ERROR_MESSAGE);
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 43
How to validate the data entered into a text field Like console applications, Swing applications should validate all
data entered by the user before processing the data.
When an entry is invalid, the program needs to display an error message and give the user another chance to enter valid data.
To test whether a value has been entered into a text field, you can use the getText method of the text field to get a string that contains the text the user entered. Then, you can check whether the length of that string is zero by using its length method.
To test whether a text field contains valid numeric data, you can code the statement that converts the data in a try block and use a catch block to catch a NumberFormatException.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 44
Code that checks if an entry has been made if (investmentTextField.getText().length() == 0) { JOptionPane.showMessageDialog(this, "Monthly Investment is " + "a required field.\nPlease re-enter.", "Invalid Entry", JOptionPane.ERROR_MESSAGE); investmentTextField.requestFocusInWindow(); validData = false; }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 45
Code that checks if an entry is a valid number try { double d = Double.parseDouble( investmentTextField.getText()); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(this, "Monthly Investment " + "must be a valid number.\nPlease re-enter.", "Invalid Entry", JOptionPane.ERROR_MESSAGE); investmentTextField.requestFocusInWindow(); validData = false; }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 46
The code for the SwingValidator class import javax.swing.*; import javax.swing.text.JTextComponent; public class SwingValidator { public static boolean isPresent(JTextComponent c, String title) { if (c.getText().length() == 0) { showMessage(c, title + " is a required field.\n" + "Please re-enter."); c.requestFocusInWindow(); return false; } return true; }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 47
The code for the SwingValidator class (continued) public static boolean isInteger(JTextComponent c, String title) { try { int i = Integer.parseInt(c.getText()); return true; } catch (NumberFormatException e) { showMessage(c, title + " must be an integer.\n" + "Please re-enter."); c.requestFocusInWindow(); return false; } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 48
The code for the SwingValidator class (continued) public static boolean isDouble(JTextComponent c, String title) { try { double d = Double.parseDouble(c.getText()); return true; } catch (NumberFormatException e) { showMessage(c, title + " must be a valid number.\n" + "Please re-enter."); c.requestFocusInWindow(); return false; } } private static void showMessage(JTextComponent c, String message) { JOptionPane.showMessageDialog(c, message, "Invalid Entry", JOptionPane.ERROR_MESSAGE); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 49
How to validate multiple entries When more than one field needs to be validated, it is best to put
all the validation logic in a separate method that returns a boolean value to indicate whether or not the data is valid.
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 50
Code that validates multiple entries with a series of if statements public boolean isValidData() { // validate investmentTextField if (!SwingValidator.isPresent(investmentTextField, "Monthly Investment")) return false; if (!SwingValidator.isDouble(investmentTextField, "Monthly Investment")) return false; // validate rateTextField if (!SwingValidator.isPresent(rateTextField, "Interest Rate")) return false; if (!SwingValidator.isDouble(rateTextField, "Interest Rate")) return false; // validate yearsTextField if (!SwingValidator.isPresent(yearsTextField, "Number of Years")) return false; if (!SwingValidator.isInteger(yearsTextField, "Number of Years")) return false; return true; }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 51
Code that validates multiple entries with a compound condition public boolean isValidData() { return SwingValidator.isPresent(investmentTextField, "Monthly Investment") && SwingValidator.isDouble(investmentTextField, "Monthly Investment") && SwingValidator.isPresent(rateTextField, "Interest Rate") && SwingValidator.isDouble(rateTextField, "Interest Rate") && SwingValidator.isPresent(yearsTextField, "Number of Years") && SwingValidator.isInteger(yearsTextField, "Number of Years"); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 52
Code that calls the isValidData method from an action event listener public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == calculateButton) { if (isValidData()) { // code that processes the data } } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 53
The Product Maintenance frame
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 54
Typical dialog boxes displayed when invalid data is entered in the Product Maintenance application
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 55
The Product Maintenance application import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.ArrayList; public class ProductMaintenanceApp { public static void main(String[] args) { JFrame frame = new ProductMaintenanceFrame(); frame.setVisible(true); } } class ProductMaintenanceFrame extends JFrame { public ProductMaintenanceFrame() { setTitle("Product Display"); setResizable(false); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.add(new ProductMaintenancePanel()); this.pack(); centerWindow(this); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 56
The Product Maintenance application (continued) private void centerWindow(Window w) { Toolkit tk = Toolkit.getDefaultToolkit(); Dimension d = tk.getScreenSize(); setLocation((d.width-w.getWidth())/2, (d.height-w.getHeight())/2); } } class ProductMaintenancePanel extends JPanel { ProductDAO productDAO; ArrayList<Product> products; Product newProduct = null; ProductSelectorPanel selectorPanel; ProductDisplayPanel productPanel; ProductButtonPanel buttonPanel;
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 57
The Product Maintenance application (continued) public ProductMaintenancePanel() { // fill the products ArrayList productDAO = DAOFactory.getProductDAO(); products = productDAO.getProducts(); // add the panels setLayout(new GridBagLayout()); selectorPanel = new ProductSelectorPanel(); add(selectorPanel, getConstraints( 0,0,1,1, GridBagConstraints.EAST)); productPanel = new ProductDisplayPanel(); add(productPanel, getConstraints( 0,1,1,1, GridBagConstraints.EAST)); buttonPanel = new ProductButtonPanel(); add(buttonPanel, getConstraints( 0,2,1,1, GridBagConstraints.EAST)); // set the initial product to be displayed productPanel.showProduct(products.get(0)); selectorPanel.selectProduct(products.get(0)); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 58
The Product Maintenance application (continued) // a method for setting grid bag constraints private GridBagConstraints getConstraints(int gridx, int gridy, int gridwidth, int gridheight, int anchor) { GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(5, 5, 5, 5); c.ipadx = 0; c.ipady = 0; c.gridx = gridx; c.gridy = gridy; c.gridwidth = gridwidth; c.gridheight = gridheight; c.anchor = anchor; return c; } class ProductSelectorPanel extends JPanel implements ActionListener { public JComboBox productComboBox; private JLabel productLabel;
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 59
The Product Maintenance application (continued) boolean filling = false; // used to indicate the // combo box is being filled public ProductSelectorPanel() { // set panel layout setLayout(new FlowLayout(FlowLayout.LEFT)); // product label productLabel = new JLabel("Select Product:"); add(productLabel); // product combo box productComboBox = new JComboBox(); fillComboBox(products); productComboBox.addActionListener(this); add(productComboBox); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 60
The Product Maintenance application (continued) public void actionPerformed(ActionEvent e) { if (!filling) { Product p = (Product)productComboBox.getSelectedItem(); productPanel.showProduct(p); } } public void fillComboBox(ArrayList<Product> a) { filling = true; productComboBox.removeAllItems(); for (Product p : a) productComboBox.addItem(p); filling = false; } public void selectProduct(Product p) { productComboBox.setSelectedItem(p); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 61
The Product Maintenance application (continued) public Product getCurrentProduct() { return (Product) productComboBox.getSelectedItem(); } } class ProductDisplayPanel extends JPanel { public JTextField codeTextField, descriptionTextField, priceTextField; private JLabel codeLabel, descriptionLabel, priceLabel; public ProductDisplayPanel() { // set panel layout setLayout(new GridBagLayout());
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 62
The Product Maintenance application (continued) // code label codeLabel = new JLabel("Product Code:"); add(codeLabel, getConstraints( 0,0,1,1, GridBagConstraints.EAST));
// code text field codeTextField = new JTextField(10); codeTextField.setEditable(false); codeTextField.setFocusable(false); codeTextField.addFocusListener(new AutoSelect()); add(codeTextField, getConstraints( 1,0,1,1, GridBagConstraints.WEST));
// description label descriptionLabel = new JLabel("Desription:"); add(descriptionLabel, getConstraints( 0,1,1,1, GridBagConstraints.EAST));
// description text field descriptionTextField = new JTextField(30); descriptionTextField.setEditable(false); descriptionTextField.setFocusable(false); descriptionTextField.addFocusListener(new AutoSelect()); add(descriptionTextField, getConstraints( 1,1,1,1, GridBagConstraints.WEST));
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 63
The Product Maintenance application (continued) // price label priceLabel = new JLabel("Unit Price:"); add(priceLabel, getConstraints( 0,2,1,1, GridBagConstraints.EAST)); // price text field priceTextField = new JTextField(10); priceTextField.setEditable(false); priceTextField.setFocusable(false); priceTextField.addFocusListener(new AutoSelect()); priceTextField.addKeyListener(new NumFilter()); add(priceTextField, getConstraints( 1,2,1,1, GridBagConstraints.WEST)); } public void showProduct(Product p) { codeTextField.setText(p.getCode()); descriptionTextField.setText(p.getDescription()); priceTextField.setText(p.getFormattedPrice()); }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 64
The Product Maintenance application (continued) public void clearFields() { codeTextField.setText(""); descriptionTextField.setText(""); priceTextField.setText(""); } // return a Product object with the data in the text fields public Product getProduct() { Product p = new Product(); p.setCode(codeTextField.getText()); p.setDescription(descriptionTextField.getText()); p.setPrice(Double.parseDouble( priceTextField.getText())); return p; } public void setAddMode() { codeTextField.setEditable(true); codeTextField.setFocusable(true); codeTextField.requestFocusInWindow(); descriptionTextField.setEditable(true);
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 65
The Product Maintenance application (continued) descriptionTextField.setFocusable(true); priceTextField.setEditable(true); priceTextField.setFocusable(true); } public void setEditMode() { descriptionTextField.setEditable(true); descriptionTextField.setFocusable(true); descriptionTextField.requestFocusInWindow(); priceTextField.setEditable(true); priceTextField.setFocusable(true); } public void setDisplayMode() { codeTextField.setEditable(false); codeTextField.setFocusable(false); descriptionTextField.setEditable(false); descriptionTextField.setFocusable(false); priceTextField.setEditable(false); priceTextField.setFocusable(false); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 66
The Product Maintenance application (continued) class ProductButtonPanel extends JPanel { public JButton addButton, editButton, deleteButton, acceptButton, cancelButton, exitButton; public ProductButtonPanel() { // create maintenance button panel JPanel maintPanel = new JPanel(); maintPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); // add button addButton = new JButton("Add"); addButton.addActionListener(new AddListener()); maintPanel.add(addButton); // edit button editButton = new JButton("Edit"); editButton.addActionListener(new EditListener()); maintPanel.add(editButton);
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 67
The Product Maintenance application (continued) // delete button deleteButton = new JButton("Delete"); deleteButton.addActionListener(new DeleteListener()); maintPanel.add(deleteButton); // accept button acceptButton = new JButton("Accept"); acceptButton.setEnabled(false); acceptButton.addActionListener(new AcceptListener()); maintPanel.add(acceptButton); // cancel button cancelButton = new JButton("Cancel"); cancelButton.setEnabled(false); cancelButton.addActionListener(new CancelListener()); maintPanel.add(cancelButton); // create exit button panel JPanel exitPanel = new JPanel(); exitPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 68
The Product Maintenance application (continued) // exit button exitButton = new JButton("Exit"); exitButton.addActionListener(new ExitListener()); exitPanel.add(exitButton); // add panels to the ProductButtonPanel setLayout(new BorderLayout()); add(maintPanel, BorderLayout.CENTER); add(exitPanel, BorderLayout.SOUTH); } public void setAddEditMode(boolean e) { addButton.setEnabled(!e); editButton.setEnabled(!e); deleteButton.setEnabled(!e); acceptButton.setEnabled(e); cancelButton.setEnabled(e); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 69
The Product Maintenance application (continued) class AddListener implements ActionListener { public void actionPerformed(ActionEvent e) { newProduct = new Product(); productPanel.clearFields(); buttonPanel.setAddEditMode(true); productPanel.setAddMode(); } } class EditListener implements ActionListener { public void actionPerformed(ActionEvent e) { buttonPanel.setAddEditMode(true); productPanel.setEditMode(); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 70
The Product Maintenance application (continued) class DeleteListener implements ActionListener { public void actionPerformed(ActionEvent e) { Product p = productPanel.getProduct(); productDAO.deleteProduct(p); products.remove(p); selectorPanel.fillComboBox(products); selectorPanel.selectProduct(products.get(0)); productPanel.showProduct(products.get(0)); selectorPanel.productComboBox.requestFocusInWindow(); } } class AcceptListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (isValidData()) { if (newProduct != null) { newProduct = productPanel.getProduct(); productDAO.addProduct(newProduct);
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 71
The Product Maintenance application (continued) products.add(newProduct); selectorPanel.fillComboBox(products); selectorPanel.selectProduct(newProduct); newProduct = null; } else { Product p = selectorPanel.getCurrentProduct(); Product newProduct = productPanel.getProduct(); p.setDescription(newProduct.getDescription()); p.setPrice(newProduct.getPrice()); productDAO.updateProduct(p); selectorPanel.fillComboBox(products); selectorPanel.selectProduct(p); productPanel.showProduct( selectorPanel.getCurrentProduct()); } productPanel.setDisplayMode(); buttonPanel.setAddEditMode(false); selectorPanel.productComboBox.requestFocusInWindow(); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 72
The Product Maintenance application (continued) public boolean isValidData() { if (newProduct != null) return SwingValidator.isPresent( productPanel.codeTextField, "Product Code") && SwingValidator.isPresent( productPanel.descriptionTextField, "Description") && SwingValidator.isPresent( productPanel.priceTextField, "Unit Price") && SwingValidator.isDouble( productPanel.priceTextField, "Unit Price"); else return SwingValidator.isPresent( productPanel.descriptionTextField, "Description") && SwingValidator.isPresent( productPanel.priceTextField, "Unit Price") && SwingValidator.isDouble( productPanel.priceTextField, "Unit Price"); } }
Murach’s Beg. Java 2, JDK 5, C17 © 2005, Mike Murach & Associates, Inc. Slide 73
The Product Maintenance application (continued) class CancelListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (newProduct != null) { newProduct = null; } productPanel.setDisplayMode(); productPanel.showProduct( selectorPanel.getCurrentProduct()); buttonPanel.setAddEditMode(false); selectorPanel.productComboBox.requestFocusInWindow(); } } class ExitListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.exit(0); } } }