COMP1406/1006 - Design and Implementation of Computer Applications |
Winter 2006
|
6 Menus and Dialogs |
Here are the individual topics found in this set of notes (click on one to go there):
6.1 Using Menus |
What is Menu?
What are the main Menu Classes? |
![]() |
JMenuItem findItem = new JMenuItem("Find");
JMenuItem replaceItem = new JMenuItem("Replace");
searchMenu.add(findItem);
searchMenu.add(replaceItem);
A standard menu |
A cascaded menu |
A menu with radio buttons |
A pop-up menu |
The example shows how the use of many menu items can lead to a lot of instance variables. In addition, we use a common event handler for all menu items and apply a dispatching strategy which calls the appropriate react method for the given menu item. We could have omitted the react methods and merely placed all this code within the single event handler but this could look messy if the react methods are large.
How would the example look if we used anonymous classes instead of one event handler ? It may not save much in code size but we only need to update the class in one place instead of two when a menu item is added or removed! Also, we might not need to keep all the menu items in instance variables! Why not give it a try and see what it looks like.
import java.awt.event.*;
import javax.swing.*;
public class MenuExample extends JFrame implements ActionListener {
// Store menu items and popup menu for access from event handlers}
JMenuItem thinkItem, copyItem, newItem, openItem, saveAsItem,
findItem, replaceItem, appleItem, orangeItem,
bannanaItem, helpItem, inspectItem;JPopupMenu popupMenu;
public MenuExample(String title) {
super(title);// Create the menu bar
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
// Create and Add the File menu to the Menu Bar
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic('F');
fileMenu.add(newItem = new JMenuItem("New", 'N'));
fileMenu.add(new JSeparator());
fileMenu.add(openItem = new JMenuItem("Open", 'O'));
fileMenu.add(saveAsItem = new JMenuItem("Save As"));
menuBar.add(fileMenu); // Don't forget to do this
newItem.addActionListener(this);
openItem.addActionListener(this);
saveAsItem.addActionListener(this);
// Create and Add the Edit menu to the Menu Bar
JMenu editMenu = new JMenu("Edit");
editMenu.setMnemonic('E');
editMenu.add(thinkItem = new JMenuItem("Think", new ImageIcon("brain.gif")));
editMenu.add(copyItem = new JMenuItem("Copy"));
menuBar.add(editMenu);
thinkItem.addActionListener(this);
copyItem.addActionListener(this);
// Create and Add the Settings menu to the Menu Bar
JMenu settingsMenu = new JMenu("Settings");
settingsMenu.setMnemonic('S');
settingsMenu.add(appleItem = new JRadioButtonMenuItem("Apples"));
settingsMenu.add(orangeItem = new JRadioButtonMenuItem("Oranges"));
settingsMenu.add(bannanaItem = new JRadioButtonMenuItem("Bannanas"));
menuBar.add(settingsMenu);
// Ensure that only one radio button is on at a time
ButtonGroup fruits = new ButtonGroup();
fruits.add(appleItem);
fruits.add(orangeItem);
fruits.add(bannanaItem);
// Create the cascading Search menu on the Settings menu
JMenu searchMenu = new JMenu("Search");
searchMenu.add(findItem = new JMenuItem("Find"));
searchMenu.add(replaceItem = new JMenuItem("Replace"));
editMenu.add(searchMenu);
findItem.addActionListener(this);
replaceItem.addActionListener(this);
// Create and Add items to the popup menu. Notice
// that we do not add the popup menu to anything.
popupMenu = new JPopupMenu();
popupMenu.add(helpItem = new JMenuItem("help"));
popupMenu.add(inspectItem = new JMenuItem("inspect"));
helpItem.addActionListener(this);
inspectItem.addActionListener(this);
// Register the event handler for the popup menu
addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e){
if (e.isPopupTrigger())
popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
});setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 300);
}
// Handle all menu selections and dispatch to the appripriate helper method accordingly
public void actionPerformed(ActionEvent e){if (e.getSource() == newItem)}
reactToNewMenuSelection();
else if (e.getSource() == openItem)
reactToOpenMenuSelection();
else if (e.getSource() == saveAsItem)
reactToSaveAsMenuSelection();
else if (e.getSource() == copyItem)
reactToCopyMenuSelection();
else if (e.getSource() == thinkItem)
reactToThinkMenuSelection();
else if (e.getSource() == findItem)
reactToFindMenuSelection();
else if (e.getSource() == replaceItem)
reactToReplaceMenuSelection();
else if (e.getSource() == helpItem)
reactToHelpMenuSelection();
else if (e.getSource() == inspectItem)
reactToInspectMenuSelection();
// Here are all the helper methods for handling the menu choices
public void reactToNewMenuSelection() {
System.out.println("reacting to NEW selection from menu");
}
public void reactToOpenMenuSelection() {
System.out.println("reacting to OPEN selection from menu");
}
public void reactToSaveAsMenuSelection() {
System.out.println("reacting to SAVE AS selection from menu");
}
public void reactToThinkMenuSelection() {
System.out.println("reacting to THINK selection from menu");
}
public void reactToCopyMenuSelection() {
System.out.println("reacting to COPY selection from menu");
}
public void reactToFindMenuSelection() {
System.out.println("reacting to FIND selection from menu");
}
public void reactToReplaceMenuSelection() {
System.out.println("reacting to REPLACE selection from menu");
}
public void reactToHelpMenuSelection() {
System.out.println("reacting to HELP selection from popup menu");
}
public void reactToInspectMenuSelection() {
System.out.println("reacting to INSPECT selection from popup menu");
}
public static void main(String args[]) {
new MenuExample("Menu Example").setVisible(true);
}
6.2 Standard Dialog Boxes |
When using one of these standard dialog boxes, you may specify:
Here is the code for our test application. Notice the output
that appears in the
console when running the code. You should be able to figure out
how to get information
easily from your dialog boxes from this example.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class StandardDialogTester extends
JFrame {
public StandardDialogTester
(String title) {
super(title);
setLayout(new
GridLayout(3, 3));
JButton aButton;
add(aButton
= new
JButton("Plain Message Box"));
aButton.addActionListener(new ActionListener()
{
public void
actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,
"This
is a plain message !!!",
"Read This",
JOptionPane.PLAIN_MESSAGE);
}});
add(aButton
= new
JButton("Warning Message Box"));
aButton.addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,
"Don't
eat yellow snow.",
"Warning",
JOptionPane.WARNING_MESSAGE);
}});
add(aButton
= new
JButton("Error Message Box"));
aButton.addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,
"Your program has stopped
working !",
"Error",
JOptionPane.ERROR_MESSAGE);
}});
add(aButton
= new
JButton("Information Message Box"));
aButton.addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,
"You
better pass the final exam or else ...",
"Information",
JOptionPane.INFORMATION_MESSAGE);
}});
add(aButton
= new
JButton("Confirmation Dialog Box"));
aButton.addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
int
result = JOptionPane.showConfirmDialog(null,
"Do you want me to erase your hard drive ?",
"Answer
this Question",
JOptionPane.YES_NO_OPTION);
if
(result == 0)
System.out.println("OK, I'm
erasing it now ...");
else
System.out.println("Fine then, you clean it up!");
}});
add(aButton
= new
JButton("Confirmation Dialog Box with Cancel"));
aButton.addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
int
result = JOptionPane.showConfirmDialog(null,
"Do you want to overwrite the file ?",
"Answer
this Question",
JOptionPane.YES_NO_CANCEL_OPTION);
switch(result)
{
case
0: System.out.println("OK, but don't come crying
to me once its gone"); break;
case
1: System.out.println("Well you should pick a new
name
then"); break;
case
2: System.out.println("OK, I'll ask you again
later"); break;
}
}});
add(aButton
= new
JButton("Multiple Option Dialog Box"));
aButton.addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
Object[] options = {"Outstanding",
"Excellent", "Good",
"Fair", "Poor"};
int
result = JOptionPane.showOptionDialog(null,
"How would you rate your
vehicle's performance ?",
"Pick
an Option",
JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
System.out.print("You have
rated your vehicle's performance as "
+ options[result]);
if
(result < 3)
System.out.println("We are glad you are pleased.");
else
System.out.println("Please explain why.");
}});
add(aButton
= new
JButton("Input Dialog Box"));
aButton.addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
String inputValue =
JOptionPane.showInputDialog("Please
input your name");
System.out.println("Your name
is " +
inputValue);
}});
add(aButton
= new
JButton("Chooser Dialog Box"));
aButton.addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
Object[] options = {"Apple",
"Orange", "Strawberry",
"Bannana", "Cherry"};
Object selectedValue = JOptionPane.showInputDialog(null,
"Choose your favorite fruit",
"Fruit Information",
JOptionPane.INFORMATION_MESSAGE,
null,
options,
options[1]);
System.out.println(selectedValue + "s sure do
taste yummy.");
}});
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); //chooses reasonable window size based on component
prefered sizes
}
public static void
main(String args[]) {
new StandardDialogTester("Standard
Dialog Tester").setVisible(true);
}
}
Here are the dialog boxes that will appear.
Plain Message Box:
Information Message Box:
Error Message Box:
Information Message Box:
Confirmation Dialog Box:
Confirmation Dialog Box with Cancel:
Select Option Dialog Box:
Input Dialog Box:
Option Dialog Box:
There is another useful standard dialog box in JAVA that is used for selecting files. It is called a JFileChooser.
Here is what it looks like:
Here is some code that opens up a JFileChooser box and
displays the filename (no path) that the user selects.
JFileChooser chooser = new JFileChooser();There are more options available that allow you to set the filters and starting directories. Take a look at the Swing API.
int returnVal = chooser.showOpenDialog(this);if (returnVal == JFileChooser.APPROVE_OPTION) {
System.out.println("You chose to open this file: " +
chooser.getSelectedFile().getName());
}
6.3 Creating Your Own Dialog Boxes |
There are two important terms pertaining to dialog boxes:
Here is how everything should work:
Notice that the model is used as the "middle-man" between the two windows:
public interface DialogClientInterface {So, if the client class implements this interface, it will be sure to have these two methods:
public void dialogFinished();
public void dialogCancelled();
}
public class MyApplication implements DialogClientInterface {Now, since the client application class implements the interface, all other classes know that they can call the dialogFinished() method or the dialogCancelled() method.
...
...
public void dialogFinished() {
...
}
public void dialogCancelled() {
...
}
...
}
Why would we want to call these methods from outside this class ? Dialog boxes are defined in separate classes, so the client (i.e., usually the main application) has no idea what is going on within those classes (nor should it need to know). The client does, however, need to know the following:
public class SomeDialog extends JDialog {Here are the steps involved with creating a dialog box:
// The client (usually the caller of this dialog box)
private DialogClientInterface client;// A constructor that takes the model and client as parameters
public SomeDialog(Frame owner, ...){
...
}private void okButtonPressed() {
...
((DialogClientInterface)this.getOwner()).dialogFinished();
}
private void cancelButtonPressed() {
...
((DialogClientInterface)this.getOwner()).dialogCancelled();
}
}
In some cases, we may not want the user of the dialog box to decide whether or not it should be modal, nor may we want them to specify the title. We can simply hard-code these into the dialog box if we wish:In addition to this, we will use the dispose() message to dispose of (i.e., close and delete) the dialog box from within your code.
public MyDialog(Frame owner, ClassA modelA, ClassB modelB, ...) {super(owner, "Mt Cool Dialog Box", true);
...
}
In this example we will create a BankAccountDialog that allows us to modify a BankAccount's owner name, address and phone number. It will also show us the account number and balance, but we will not be allowed to alter that information. We use an extended version of the BankAccount class that was used in COMP1405/1005 (we added here an address and phone number). We will design the dialog box to look like this:
Notice that it shows the name, address, phone number, account number and balance, but that the account number and balance are disabled (grayed out) so that we cannot edit them. Also, notice the OK and CANCEL buttons (which typically appear at the bottom right of a dialog box). Also, notice that there are no minimize or maximize buttons on the titlebar ... we will make this window non-resizable.![]()
We will create this window by first creating a JPanel containing the 5 text fields and their labels. We will set it up as the view part of the window so that the panel class will not have any behaviour, it will simply allow us to access the 3 editable fields through public get methods.
import java.awt.*;Notice:
import javax.swing.*;
public class BankAccountPanel extends JPanel {
// The components needed to be used outside of this class
private JTextField nameTextField;
private JTextField addressTextField;
private JTextField phoneTextField;// Make a get method so that the name/address/phone can be accessed externally
public JTextField getNameTextField() { return nameTextField; }
public JTextField getAddressTextField() { return addressTextField; }
public JTextField getPhoneTextField() { return phoneTextField; }// Add a constructor that takes a BankAccount, so that we can populate the text fields
public BankAccountPanel (BankAccount account) {// Fill in the text fields with bank account's information
nameTextField = new JTextField(account.getName());
addressTextField = new JTextField(account.getAddress());
phoneTextField = new JTextField(account.getPhone());JTextField accField = new JTextField(String.valueOf(account.getAccountNumber()));
JTextField balField = new JTextField(String.valueOf(account.getBalance()));// Disallow changing of balance and account number
accField.setEnabled(false);
balField.setEnabled(false);// Set the layoutManager and add the components
setLayout(new GridLayout(5,3,5,5));
add(new JLabel("Name:"));
add(nameTextField);
add(new JLabel("Address:"));
add(addressTextField);
add(new JLabel("Phone Number:"));
add(phoneTextField);
add(new JLabel("Account #:"));
add(accField);
add(new JLabel("Balance:"));
add(balField);
}
}
import java.awt.*;Notice:
import java.awt.event.*;
import javax.swing.*;
public class BankAccountDialog extends JDialog {
private BankAccount account; // The model// The buttons and main panel
private JButton okButton;
private JButton cancelButton;
private BankAccountPanel bankAccountPanel;
// A constructor that takes the model and client as parameters
public BankAccountDialog(Frame owner, String title, boolean modal, BankAccount acc) {// Call the super constructor that does all the work of setting up the dialog
super(owner,title,modal);
account = acc; // Store the model// Make a panel with two buttons (placed side by side)
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
buttonPanel.add(okButton = new JButton("OK"));
buttonPanel.add(cancelButton = new JButton("CANCEL"));// Make the dialog box by adding the bank account panel and the button panel
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
bankAccountPanel = new BankAccountPanel(account);
add(bankAccountPanel);
add(buttonPanel);// Prevent the window from being resized
setResizable(false);// Listen for ok button click
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event){
okButtonClicked();
}});// Listen for cancel button click
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event){
cancelButtonClicked();
}});// Listen for window closing: treat like cancel button
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
cancelButtonClicked();
}});// Set the size of the dialog box
setSize(300, 190);
}private void okButtonClicked(){
// Update model to show changed owner name
account.setName(bankAccountPanel.getNameTextField().getText());
account.setAddress(bankAccountPanel.getAddressTextField().getText());
account.setPhone(bankAccountPanel.getPhoneTextField().getText());// Tell the client that ok was clicked, in case something needs to be done there
if (getOwner() != null)
((DialogClientInterface)getOwner()).dialogFinished();dispose(); // destroy this dialog box
}private void cancelButtonClicked(){
// Tell the client that cancel was clicked, in case something needs to be done there
if (client != null)
((DialogClientInterface)getOwner()).dialogCancelled();dispose(); // destroy this dialog box
}
}
This application will maintain a BankAccount object as the model and show its contents in a JTextArea object. When the user clicks the Edit Account button, we will create/open the dialog box. The dialog box will be modal, so we will have to finish working with it before we go back to the main window here. Once the dialog box has been closed, any changes that were made should be reflected in the text area. Here is the code:![]()
public BankAccountEditor(String
title, BankAccount account){
super(title);
model = account; // store the model
// create a text area and an edit button
info = new
JTextArea();
JButton editButton = new
JButton("Edit Account");
editButton.addActionListener(this);
setLayout(new
BoxLayout(getContentPane(),
BoxLayout.Y_AXIS));
add(info);
add(editButton);
update(); // fill in the text area
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 150);
}
// Handle the EDIT
button
public void actionPerformed(ActionEvent
e) {
//
Create a new dialog box
BankAccountDialog
dialog = new BankAccountDialog (this,
"Edit Account", true, model);
System.out.println("About to open the dialog box
...");
dialog.setVisible(true); // Open the dialog box
System.out.println("Dialog box has been closed.");
}
public void
dialogFinished() {
System.out.println("Changes accepted, Account has been changed");
update();
}
public void
dialogCancelled() {
System.out.println("Changes aborted, Account has not been changed");
//no
need to call update, since nothing has changed
}
private void update() {
//update
the info text area to reflect the account balance
info.setText(
model.getName() + '\n' + model.getAddress() + '\n' +
model.getPhone() + '\n' + model.getAccountNumber() + '\n' +
model.getBalance());
}
public static void main(String
args[]) {
BankAccount b = new
BankAccount("Rob Banks", "279 Lois Lane", "555-1234");
b.deposit(500);
BankAccountEditor
frame = new BankAccountEditor("Testing a
DialogBox", b);
frame.setVisible(true);
}
}
6.4 E-mail Buddy Dialog Box Example |
What exactly is an e-mail buddy ? Well we can easily develop a model of an EmailBuddy as follows:
// This class represents a "buddy" whose email address is kept.As can be seen, there is nothing difficult here ... just your standard "run-of-the-mill" model class. However, this class alone doe not represent the whole model for our GUI since we will have many of these EmailBuddy objects. So, we will make a Vector of them when we make the interface.
// An additional boolean indicates whether or not this is a
// friend that is "hot" (i.e. contacted often)
public class EmailBuddy {
private String name;
private String address;
private boolean onHotList;// Here are some constructors
public EmailBuddy() {
name = "";
address = "";
onHotList = false;
}
public EmailBuddy(String aName, String anAddress) {
name = aName;
address = anAddress;
onHotList = false;
}// Here are the get methods
public String getName() { return name; }
public String getAddress() { return address; }
public boolean onHotList() { return onHotList; }// Here are the set methods
public void setName(String newName) { name = newName; }
public void setAddress(String newAddress) { address = newAddress; }
public void onHotList(boolean onList) { onHotList = onList; }// The appearance of the buddy
public String toString() {
return(name);
}
}
The task now is to design a nice interface for the main application. To start, we must decide what the interface should do. Here is a possible interface:
Notice that the interface does not show the e-mail addresses in the list. It may look cluttered, but we could certainly have done this. Perhaps we could have made a second list box or something that would show the e-mail addresses. Here is a good exercise: make a JTextField just beneath the list that will show the e-mail address of the currently selected EmailBuddy in the list. This is not hard to do. Nevertheless, it is not necessary for the purposes of explaining this dialog box example.
How can we build the view for this interface ? We will start with a JPanel. We will use GridBagLayout to allow nice resizing.
import java.awt.*;Notice that there is nothing really new here either. We did however, make some "get" methods for the components so that we can access them from outside this class.
import java.awt.event.*;
import javax.swing.*;// This is the Panel that contains represents the view of the
// Email buddy application.
public class EmailBuddyPanel extends JPanel {private JButton addButton;
private JButton removeButton;
private JList buddyList;
private JCheckBox hotListButton;// These are the get methods that are used to access the components
public JButton getAddButton() { return addButton; }
public JButton getRemoveButton() { return removeButton; }
public JCheckBox getHotListButton() { return hotListButton; }
public JList getBuddyList() { return buddyList; }// This is the default constructor
public EmailBuddyPanel(){
super();// Use a GridBagLayout (lotsa fun)
GridBagLayout layout = new GridBagLayout();
GridBagConstraints layoutConstraints = new GridBagConstraints();
setLayout(layout);// Add the buddy list
buddyList = new JList();
buddyList.setPrototypeCellValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
JScrollPane scrollPane = new JScrollPane( buddyList,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
layoutConstraints.gridx = 0; layoutConstraints.gridy = 0;
layoutConstraints.gridwidth = 3; layoutConstraints.gridheight = 5;
layoutConstraints.fill = GridBagConstraints.BOTH;
layoutConstraints.insets = new Insets(10, 10, 10, 10);
layoutConstraints.anchor = GridBagConstraints.NORTHWEST;
layoutConstraints.weightx = 1.0; layoutConstraints.weighty = 1.0;
layout.setConstraints(scrollPane, layoutConstraints);
add(scrollPane);// Add the Add button
addButton = new JButton("Add");
layoutConstraints.gridx = 3; layoutConstraints.gridy = 0;
layoutConstraints.gridwidth = 1; layoutConstraints.gridheight = 1;
layoutConstraints.fill = GridBagConstraints.BOTH;
layoutConstraints.insets = new Insets(10, 10, 10, 10);
layoutConstraints.anchor = GridBagConstraints.EAST;
layoutConstraints.weightx = 0.0; layoutConstraints.weighty = 0.0;
layout.setConstraints(addButton, layoutConstraints);
add(addButton);// Add the Remove button
removeButton = new JButton("Remove");
layoutConstraints.gridx = 3; layoutConstraints.gridy = 1;
layoutConstraints.gridwidth = 1; layoutConstraints.gridheight = 1;
layoutConstraints.fill = GridBagConstraints.BOTH;
layoutConstraints.insets = new Insets(10, 10, 10, 10);
layoutConstraints.anchor = GridBagConstraints.EAST;
layoutConstraints.weightx = 0.0; layoutConstraints.weighty = 0.0;
layout.setConstraints(removeButton, layoutConstraints);
add(removeButton);// Add the ShowHotList button
hotListButton = new JCheckBox("Show Hot List");
layoutConstraints.gridx = 3; layoutConstraints.gridy = 3;
layoutConstraints.gridwidth = 1; layoutConstraints.gridheight = 1;
layoutConstraints.fill = GridBagConstraints.BOTH;
layoutConstraints.insets = new Insets(10, 10, 10, 10);
layoutConstraints.anchor = GridBagConstraints.EAST;
layoutConstraints.weightx = 0.0; layoutConstraints.weighty = 0.0;
layout.setConstraints(hotListButton, layoutConstraints);
add(hotListButton);
}
}
Now for the actual dialog box. Ask yourself these questions:
Here are some more questions that need to be answered:
Don't forget that we need to add the OK and CANCEL buttons as well. Also, there is no need to be able to resize the dialog box so we can just disable the resizing.
Below is a method that will be called from our dialog class to add the components to the dialog box. It will take an EmailBuddy object as a parameter so that when the dialog box opens, we can populate the text fields with values indicating the EmailBuddy's current information. This parameter will represent the model that is affected by the dialog box.
// This code adds the
necessary components to the interface
private void
buildDialogWindow(EmailBuddy
aBuddy) {
setLayout(null);
// Add the name label
aLabel = new
JLabel("Name:");
aLabel.setLocation(10,10);
aLabel.setSize(80, 30);
add(aLabel);
// Add the name field
nameField = new
JTextField(aBuddy.getName());
nameField.setLocation(110, 10);
nameField.setSize(400,
30);
add(nameField);
// Add the address label
aLabel = new
JLabel("Address:");
aLabel.setHorizontalAlignment(JLabel.LEFT);
aLabel.setLocation(10,50);
aLabel.setSize(80, 30);
add(aLabel);
// Add the address field
addressField = new
JTextField(aBuddy.getAddress());
addressField.setLocation(110, 50);
addressField.setSize(400, 30);
add(addressField);
// Add the onHotList button
hotListButton = new
JCheckBox("On Hot List");
hotListButton.setSelected(aBuddy.onHotList());
hotListButton.setLocation(110, 100);
hotListButton.setSize(120, 30);
add(hotListButton);
// Add the Ok button
okButton = new
JButton("Ok");
okButton.setLocation(300, 130);
okButton.setSize(100,
40);
add(okButton);
// Add the Cancel button
cancelButton = new
JButton("Cancel");
cancelButton.setLocation(410, 130);
cancelButton.setSize(100, 40);
add(cancelButton);
}
We will now look at the code needed to create the dialog box and get its behaviour working correctly:
import java.awt.*;Once again, we see that we just add listeners for the OK and CANCEL buttons as well as the window closing event. Then we merely make methods that are called for each.
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class BuddyDetailsDialog extends JDialog {// This is a pointer to the email buddy that is being edited
private EmailBuddy aBuddy;// These are the components of the dialog box
private JLabel aLabel;
private JTextField nameField;
private JTextField addressField;
private JCheckBox hotListButton;
private JButton okButton;
private JButton cancelButton;public BuddyDetailsDialog(Frame owner, String title, boolean modal, EmailBuddy bud){
super(owner,title,modal);aBuddy = bud;
// Put all the components onto the window and given them initial values
buildDialogWindow(aBuddy);// Add listeners for the Ok and Cancel buttons as well as window closing
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event){
okButtonClicked();
}});cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event){
cancelButtonClicked();
}});addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
cancelButtonClicked();
}});setSize(526, 214);
}private void buildDialogWindow(EmailBuddy aBuddy) {
// This code is given above
}private void okButtonClicked(){
aBuddy.setName(nameField.getText());
aBuddy.setAddress(addressField.getText());
aBuddy.onHotList(hotListButton.isSelected());
if (getOwner() != null)
((DialogClientInterface)getOwner()).dialogFinished();
dispose();
}private void cancelButtonClicked(){
if (getOwner() != null)
((DialogClientInterface)getOwner()).dialogCancelled();
dispose();
}
}
Notice that when the OK button is clicked, the 3 pieces of
changed buddy data are stored in the model buddy so that the buddy will
have been altered by this dialog box. Then we inform the client
that OK was pressed. For the cancel button, there is no
work to do, just informing the client that CANCEL was pressed.
We will call the class EmailBuddyApp and it will extend JFrame. It will be the class that opens the dialog box and so it must implement the DialogClientInterface. We will need to store the buddies that we will be making, so we make a Vector as an instance variable. We will first make the application work such that we will be able to add buddies to the list. Here is the basic framework for the application:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
public class EmailBuddyApp extends JFrame
implements DialogClientInterface {
// Store the model as a
vector of email buddies
private
Vector
// Store the view that
contains the components
EmailBuddyPanel view;
// Here are the
component listeners
ActionListener
theAddButtonListener;
// Here is the default
constructor
public EmailBuddyApp(String
title){
super(title);
//
Initially, no buddies
buddies = new
Vector
// Make a new viewing panel and add it to the pane
add(view = new
EmailBuddyPanel());
// Make a listener for the add button
theAddButtonListener =
new ActionListener() {
public
void actionPerformed(ActionEvent
event) {
addBuddy();
}};
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(600,300);
//
Start off with everything updated properly
update();
}
// Enable all listeners
private void enableListeners() {
view.getAddButton().addActionListener(theAddButtonListener);
}
// Disable all listeners
private void disableListeners() {
view.getAddButton().removeActionListener(theAddButtonListener);
}
// This is called when
the user clicks the add button
private void addBuddy() {
EmailBuddy aBuddy
= new EmailBuddy();
// Add the buddy to the end of the Vector
buddies.add(aBuddy);
// Now bring up the dialog box
BuddyDetailsDialog
dialog = new BuddyDetailsDialog(this, "Buddy Details Dialog", true,
aBuddy);
dialog.setVisible(true);
}
// Called when the
dialog box is closed with the Ok button
public void dialogFinished() {
update();
}
// Called when the
dialog box is closed with the cancel button or manually closed
public void dialogCancelled() {
//
Remove the latest buddy that was added if in add mode
buddies.remove(buddies.get(buddies.size()-1));
}
// Update the list
private void updateList() {
//
Update the list contents and select the last buddy
view.getBuddyList().setListData(buddies);
if (buddies.size>0)
view.getBuddyList().setSelectedValue((EmailBuddy)buddies.get(buddies.size()-1),
true);
}
// Update the GUI
private void update() {
disableListeners();
updateList();
enableListeners();
}
// Code that starts the
application
public static void
main(String args[]) {
EmailBuddyApp frame
= new EmailBuddyApp("Email Buddy
Application");
frame.setVisible(true);
}
}
Perhaps the most interesting portions of the code are the addBuddy(), dialogCancelled() and updateList() methods. When the user adds a buddy, we:
if (aBuddy
!= null) {
buddies.remove(aBuddy);
update();
}
}
// Add these instance variable
private
EmailBuddy
selectedBuddy;
private
ListSelectionListener buddyListSelectionListener;
//
In the constructor, make a listener to allow selection of buddies from
the list
buddyListSelectionListener = new ListSelectionListener() {
public
void valueChanged(ListSelectionEvent
event){
selectBuddy();
}};
// This is called when the user selects a buddy from the list
private void
selectBuddy() {
selectedBuddy = (EmailBuddy)(view.getBuddyList().getSelectedValue());
update();
}
// In the constructor, set the field to null
selectedBuddy = null;
private void removeBuddy() {
if
(selectedBuddy != null) {
buddies.remove(selectedBuddy);
update();
selectBuddy();
}
}
// If the hot list is on, find all buddies that are on the hot list
if
(view.getHotListButton().isSelected()) {
Vector temp = new Vector();
for
(int i=0; i<buddies.size(); i++) {
EmailBuddy aBuddy = (EmailBuddy)buddies.get(i);
if (aBuddy.onHotList()) {
temp.add(aBuddy);
if (aBuddy == selectedBuddy)
foundSelected = true;
}
}
view.getBuddyList().setListData(temp);
if (!foundSelected)
selectedBuddy = null;
}
else
view.getBuddyList().setListData(buddies);
if
(selectedBuddy != null)
view.getBuddyList().setSelectedValue(selectedBuddy, true);
}
To do this, notice that we currently have some small problems: