11.7 Custom Dialogs
The ScribbleApp
program of Example 11-15 displayed two kinds of
dialogs: a confirmation dialog created by
JOptionPane and a color selection dialog created
by JColorChooser. These Swing components support
many basic dialog box needs. The JOptionPane class
makes it easy to display simple (and not-so-simple) information,
confirmation, and selection dialogs, while
JColorChooser and JFileChooser
provide color and file selection capabilities. Most nontrivial
applications, however, need to create custom dialogs that go beyond
these standard components. This is easy to do with the
JDialog component.Example 11-17
shows the FontChooser class. It subclasses
JDialog and uses the
ItemChooser class developed in Example 11-14 to display font families, styles, and sizes to
the user. A FontChooser dialog is pictured in
Figure 11-14. The inner class
FontChooser.Demo is a simple demonstration
application you can use to experiment with the
FontChooser dialog.
Figure 11-14. The FontChooser dialog

JDialog is a
RootPaneContainer, like JFrame,
which means you can't add children to it directly.
You must instead add them to the container returned by
getContentPane( ). FontChooser
creates a modal dialog, which means that the show(
) method blocks and does not return to the caller until the
user dismisses the dialog. Finally, FontChooser is
implemented as a subclass of JDialog, so that it
can be reused by many applications. When you need to create a custom
dialog specific to a single application, you can simply create a
JDialog instance and populate it with whatever
child components you need; in other words, you do not need to write a
custom subclass to define a new dialog.
Example 11-17. FontChooser.java
package je3.gui;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import je3.gui.ItemChooser;
/**
* This is a JDialog subclass that allows the user to select a font, in any
* style and size, from the list of available fonts on the system. The
* dialog is modal. Display it with show( ); this method does not return
* until the user dismisses the dialog. When show( ) returns, call
* getSelectedFont( ) to obtain the user's selection. If the user clicked the
* dialog's "Cancel" button, getSelectedFont( ) will return null.
**/
public class FontChooser extends JDialog {
// These fields define the component properties
String family; // The name of the font family
int style; // The font style
int size; // The font size
Font selectedFont; // The Font they correspond to
// This is the list of all font families on the system
String[ ] fontFamilies;
// The various Swing components used in the dialog
ItemChooser families, styles, sizes;
JTextArea preview;
JButton okay, cancel;
// The names to appear in the "Style" menu
static final String[ ] styleNames = new String[ ] {
"Plain", "Italic", "Bold", "BoldItalic"
};
// The style values that correspond to those names
static final Integer[ ] styleValues = new Integer[ ] {
new Integer(Font.PLAIN), new Integer(Font.ITALIC),
new Integer(Font.BOLD), new Integer(Font.BOLD+Font.ITALIC)
};
// The size "names" to appear in the size menu
static final String[ ] sizeNames = new String[ ] {
"8", "10", "12", "14", "18", "20", "24", "28", "32",
"40", "48", "56", "64", "72"
};
// This is the default preview string displayed in the dialog box
static final String defaultPreviewString =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" +
"abcdefghijklmnopqrstuvwxyz\n" +
"1234567890!@#$%^&*( )_-=+[ ]{ }<,.>\n" +
"The quick brown fox jumps over the lazy dog";
/** Create a font chooser dialog for the specified frame. */
public FontChooser(Frame owner) {
super(owner, "Choose a Font"); // Set dialog frame and title
// This dialog must be used as a modal dialog. In order to be used
// as a modeless dialog, it would have to fire a PropertyChangeEvent
// whenever the selected font changed, so that applications could be
// notified of the user's selections.
setModal(true);
// Figure out what fonts are available on the system
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment( );
fontFamilies = env.getAvailableFontFamilyNames( );
// Set initial values for the properties
family = fontFamilies[0];
style = Font.PLAIN;
size = 18;
selectedFont = new Font(family, style, size);
// Create ItemChooser objects that allow the user to select font
// family, style, and size.
families = new ItemChooser("Family", fontFamilies, null, 0,
ItemChooser.COMBOBOX);
styles = new ItemChooser("Style", styleNames, styleValues, 0,
ItemChooser.COMBOBOX);
sizes = new ItemChooser("Size", sizeNames,null,4,ItemChooser.COMBOBOX);
// Now register event listeners to handle selections
families.addItemChooserListener(new ItemChooser.Listener( ) {
public void itemChosen(ItemChooser.Event e) {
setFontFamily((String)e.getSelectedValue( ));
}
});
styles.addItemChooserListener(new ItemChooser.Listener( ) {
public void itemChosen(ItemChooser.Event e) {
setFontStyle(((Integer)e.getSelectedValue( )).intValue( ));
}
});
sizes.addItemChooserListener(new ItemChooser.Listener( ) {
public void itemChosen(ItemChooser.Event e) {
setFontSize(Integer.parseInt((String)e.getSelectedValue( )));
}
});
// Create a component to preview the font.
preview = new JTextArea(defaultPreviewString, 5, 40);
preview.setFont(selectedFont);
// Create buttons to dismiss the dialog, and set handlers on them
okay = new JButton("Okay");
cancel = new JButton("Cancel");
okay.addActionListener(new ActionListener( ) {
public void actionPerformed(ActionEvent e) { hide( ); }
});
cancel.addActionListener(new ActionListener( ) {
public void actionPerformed(ActionEvent e) {
selectedFont = null;
hide( );
}
});
// Put the ItemChoosers in a Box
Box choosersBox = Box.createHorizontalBox( );
choosersBox.add(Box.createHorizontalStrut(15));
choosersBox.add(families);
choosersBox.add(Box.createHorizontalStrut(15));
choosersBox.add(styles);
choosersBox.add(Box.createHorizontalStrut(15));
choosersBox.add(sizes);
choosersBox.add(Box.createHorizontalStrut(15));
choosersBox.add(Box.createGlue( ));
// Put the dismiss buttons in another box
Box buttonBox = Box.createHorizontalBox( );
buttonBox.add(Box.createGlue( ));
buttonBox.add(okay);
buttonBox.add(Box.createGlue( ));
buttonBox.add(cancel);
buttonBox.add(Box.createGlue( ));
// Put the choosers at the top, the buttons at the bottom, and
// the preview in the middle.
Container contentPane = getContentPane( );
contentPane.add(new JScrollPane(preview), BorderLayout.CENTER);
contentPane.add(choosersBox, BorderLayout.NORTH);
contentPane.add(buttonBox, BorderLayout.SOUTH);
// Set the dialog size based on the component size.
pack( );
}
/**
* Call this method after show( ) to obtain the user's selection. If the
* user used the "Cancel" button, this will return null
**/
public Font getSelectedFont( ) { return selectedFont; }
// These are other property getter methods
public String getFontFamily( ) { return family; }
public int getFontStyle( ) { return style; }
public int getFontSize( ) { return size; }
// The property setter methods are a little more complicated.
// Note that none of these setter methods update the corresponding
// ItemChooser components as they ought to.
public void setFontFamily(String name) {
family = name;
changeFont( );
}
public void setFontStyle(int style) {
this.style = style;
changeFont( );
}
public void setFontSize(int size) {
this.size = size;
changeFont( );
}
public void setSelectedFont(Font font) {
selectedFont = font;
family = font.getFamily( );
style = font.getStyle( );
size = font.getSize( );
preview.setFont(font);
}
// This method is called when the family, style, or size changes
protected void changeFont( ) {
selectedFont = new Font(family, style, size);
preview.setFont(selectedFont);
}
// Override this inherited method to prevent anyone from making us modeless
public boolean isModal( ) { return true; }
/** This inner class demonstrates the use of FontChooser */
public static class Demo {
public static void main(String[ ] args) {
// Create some components and a FontChooser dialog
final JFrame frame = new JFrame("demo");
final JButton button = new JButton("Push Me!");
final FontChooser chooser = new FontChooser(frame);
// Handle button clicks
button.addActionListener(new ActionListener( ) {
public void actionPerformed(ActionEvent e) {
// Pop up the dialog
chooser.show( );
// Get the user's selection
Font font = chooser.getSelectedFont( );
// If not cancelled, set the button font
if (font != null) button.setFont(font);
}
});
// Display the demo
frame.getContentPane( ).add(button);
frame.setSize(200, 100);
frame.show( );
}
}
}