Dialogs are UI objects that can be used to acquire particular types of data input from the user. In this chapter, you learn how to use each of the SWT dialogs (except for PrintDialog, which is covered in Chapter 17):
This chapter first reviews the basics and then teaches you how to create custom dialogs to satisfy your own needs.
This chapter covers only those dialogs available in SWT packages. For dialogs offered by JFace packages, please refer to Chapter 18.
Dialogs are UI objects that can be used to acquire particular types of data input from the user. You use a dialog to:
The possible pseudo code is listed here:
Dialog dialog = new Dialog(shell); // 1) Creates a dialog instance. dialog.setText("Sample Dialog"); // 2) Configures the title of the dialog Object value = dialog.open(); // 3) Gets the input from the dialog ...
The org.eclipse.swt.widgets.Dialog (abstract) class is the parent class of all SWT dialogs. The Dialog class has two constructors:
public Dialog(Shell parent) public Dialog(Shell parent, int style)
To construct a dialog, you must pass a shell as its parent. If the parent is null, an IllegalArgumentException is thrown. The second constructor allows you to specify the style bits for the dialog. You can specify the modality style of the dialog with one of the following styles:
The first constructor chooses the default modality style as SWT.PRIMARY_MODAL. All the preceding modality styles are hints only because the underlying system may not support them.
Each of the concrete dialogs (e.g., ColorDialog and FileDialog) in SWT has two constructors with exactly the same arguments as those mentioned previously.
You can use the following methods of the Dialog class to get/set the title of the dialog:
public String getText() public void setText(String string)
To get the parent shell, you can use the getParent method:
public Shell getParent()
The following sections cover all dialogs available in SWT.
This section introduces two other types of dialogs: ColorDialog and FontDialog.
ColorDialog allows the user to select a color from the predefined set of available colors. Before opening a color dialog, you can use the setRGB method to set the default selected color:
public void setRGB(RGB rgb)
If null is passed to setRGB, the system tries to select a default color. The open method of the ColorDialog method returns the selected color as an RGB object or null if the user cancels the selection.
public RGB open()
FontDialog allows the user to select a font with font style, size, and effects. The open method of the FontDialog class returns the selected font as a FontData object or null if the user cancels the selection.
public FontData open()
You can create a Font object based on the FontData returned. Before opening the dialog, you can optionally set the default selected font using the setFontList method of the FontDialog class:
public void setFontList(FontData[] fontData)
A font dialog may also support color selection. You can use the following methods to get/set the selected color:
public RGB getRGB() public void setRGB(RGB rgb)
To have a better understanding of ColorDialog and FontDialog, let's build a text display application that allows the user to set the foreground color and the text font (see Figure 12-1).
Figure 12-1
The corresponding code is as follows:
public class FormattedText { Display display = new Display(); Shell shell = new Shell(display); // the label used to display the text. Label label; Button buttonColor; Button buttonFont; // current selected color. Color color; // current selected font. Font font; public FormattedText() { label = new Label(shell, SWT.BORDER | SWT.WRAP); label.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); label.setText("Java UI Programming with SWT/JFace"); buttonColor = new Button(shell, SWT.PUSH); buttonColor.setText("Change color"); buttonColor.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { ColorDialog colorDialog = new ColorDialog(shell); if(color != null) // initializes default selected color. colorDialog.setRGB(color.getRGB()); RGB value = colorDialog.open(); if(value != null) { if(color != null) color.dispose(); color = new Color(display, value); label.setForeground(color); }else{ System.out.println( "Setting foreground color action canceled."); } } }); buttonFont = new Button(shell, SWT.PUSH); buttonFont.setText("Change font"); buttonFont.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FontDialog fontDialog = new FontDialog(shell); if(font != null) // initializes default selected font. fontDialog.setFontList(font.getFontData()); FontData fontData = fontDialog.open(); if(fontData != null) { if(font != null) font.dispose(); font = new Font(display, fontData); label.setFont(font); }else{ System.out.println("Setting font action canceled."); } } }); label.setBounds(0, 0, 300, 120); buttonColor.setBounds(50, 130, 90, 25); buttonFont.setBounds(160, 130, 90, 25); shell.setSize(300, 190); shell.open(); // Set up the event loop. while (!shell.isDisposed()) { if (!display.readAndDispatch()) { // If no more entries in event queue display.sleep(); } } display.dispose(); } public static void main(String[] args) { new FormattedText(); } }
A label is created to display the text. When the change color button is pressed, a color dialog is created. If the currently selected color is known, you use its value to set the default selected color for the dialog. The dialog is displayed when colorDialog.open() is executed. If the user selects a color and presses OK, an instance of RGB representing the current selected color is returned. You first dispose of the last selected color and create a new color based on the RGB object returned. After the color object is properly constructed, you then set it as the foreground color of the label using the setForeground method of the Label class. If the color selection is canceled, a string is displayed to inform the user.
Similarly, when the change font button is pressed, a font dialog is created. Set the default font as the current selected font, if it exists. You cannot directly set the default selected font with a Font object; instead you need to use the font data information that the Font object contains. The font dialog is then opened. If the user selects a font and clicks OK in the dialog, a FontData object representing the selected font is returned. You dispose of the existing Font object, if any, and create a new one based on the FontData returned. The font of the label is changed through the setFont method.
The returned objects from these dialogs, RGBs and FontDatas, are common Java objects that can be garbage collected by the JVM. However, Color and Font objects are resource-based objects, and you must handle them with care. For a complete discuss of resource-based object management, please refer to Chapter 2.
You may find that the Eclipse IDE uses some fancy color selection buttons, as shown in Figure 12-2.
Figure 12-2
The implementation class is org.eclipse.jdt.internal.ui.preferences.ColorEditor. This class wraps a button displaying the current selected color in a narrow strip. When the button is pressed, a color dialog is displayed for the user to pick the color. The following methods of the ColorEditor class can be used to get/set the selected color:
public RGB getColorValue() public void setColorValue(RGB rgb)
In SWT, there are two kinds of dialogs that you can use to let the user select a file or directory: DirectoryDialog and FileDialog.
A DirectoryDialog allows the user to navigate the file system and to select a directory.
Before opening a directory dialog, you can set its initial directory using the setFilterPath method of the DirectoryDialog class:
public void setFilterPath(String string)
Optionally, you can provide a description of the purpose of the directory dialog using the setMessage method:
public void setMessage(String string)
The open method of the DirectoryDialog class returns the selected directory or null if the user cancels the selection:
public String open()
A FileDialog allows the user to navigate the file system and to select one or more files. In addition to modality styles, FileDialog supports the following styles:
Before opening a file dialog, you can set its initial selected directory and initial selected file name using the following methods:
public void setFilterPath(String string) public void setFileName(String string)
Both of the preceding methods can take null values.
You can use setFilterExtensions to set the file extensions that the dialog will use to filter the files. Optionally, you can provide descriptions of the filters using setFilterNames:
public void setFilterExtensions(String[] extensions) public void setFilterNames(String[] names)
For example, the following code sets three filters, as shown in Figure 12-3:
Figure 12-3
fileDialog.setFilterExtensions(new String[]{"*.rtf", "*.html", "*.*"}); fileDialog.setFilterNames(new String[]{ "Rich Text Format", "HTML Document", "Any"});
When the user selects HTML Document, the second filter, *.html, is applied. As a result, only files ending with ".html" are shown. If the third filter is applied, then files with any extension are shown.
The open method returns the absolute path of the first selected file or null if the user cancels the selection:
public String open()
To get the directory that the selected file(s) belongs to, use the getFilterPath method:
public String getFilterPath()
The getFileNames method returns the file names of all the selected files as an array:
public String[] getFileNames()
If you are interested only in the file name of the first selected file, use the getFileName method:
public String getFileName()
Both getFileNames and getFileName methods return relative file names to the filter path.
In this section, we build a simple file selection application (as shown in Figure 12-4). This application simply prints out the selected directories or files.
Figure 12-4
Here is the code for this application:
public class DirFileSelection { Display display = new Display(); Shell shell = new Shell(display); // the label used to display selected dir/file. Label label; Button buttonSelectDir; Button buttonSelectFile; String selectedDir; String fileFilterPath; public DirFileSelection() { label = new Label(shell, SWT.BORDER | SWT.WRAP); label.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); label.setText("Select a dir/file by clicking the buttons below."); buttonSelectDir = new Button(shell, SWT.PUSH); buttonSelectDir.setText("Select a directory"); buttonSelectDir.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { DirectoryDialog directoryDialog = new DirectoryDialog(shell); directoryDialog.setFilterPath(selectedDir); directoryDialog.setMessage( "Please select a directory and click OK"); String dir = directoryDialog.open(); if(dir != null) { label.setText("Selected dir: " + dir); selectedDir = dir; } } }); buttonSelectFile = new Button(shell, SWT.PUSH); buttonSelectFile.setText("Select a file/multiple files"); buttonSelectFile.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { FileDialog fileDialog = new FileDialog(shell, SWT.MULTI); fileDialog.setFilterPath(fileFilterPath); fileDialog.setFilterExtensions( new String[]{"*.rtf", "*.html", "*.*"}); fileDialog.setFilterNames(new String[]{ "Rich Text Format", "HTML Document", "Any"}); String firstFile = fileDialog.open(); if(firstFile != null) { fileFilterPath = fileDialog.getFilterPath(); String[] selectedFiles = fileDialog.getFileNames(); StringBuffer sb = new StringBuffer( "Selected files under dir " + fileDialog.getFilterPath() + ": "); for(int i=0; i
When the user presses the directory selection button, a DirectoryDialog is created. You then set the initial directory and the description using the setFilterPath method and the setMessage method, respectively. The dialog is then opened. If the user clicks OK, the selected directory is returned and printed on the label.
If the user presses the file selection button, a FileDialog is created. First, the initial directory for the dialog is set. Then, filter extensions and their corresponding descriptions are set using the setFilterExtensions method and setFilterNames, respectively. The dialog is then opened. If the user selects one or more files and clicks OK, the open method returns the absolute path of the first selected file. You then obtain the directory-selected files belonging to the getFilterPath method. The file name of each of the selected files is printed on the label.
You might notice that neither FileDialog nor DirectoryDialog allows the user to select multiple items. The primary reason is that not all platforms support multiple item selection. If you need advanced dialogs for selecting files and directories, you have to create custom dialogs, which you learn about later in this chapter.
A message box is used to inform or warn the user.
You can specify the icon and buttons to be displayed on a message box using the following styles:
Before opening a message box, you can optionally set a description for it using the setMessage method:
public void setMessage(String string)
This message is displayed below the dialog title and above the buttons.
The open method returns the ID of the button selected by the user:
public int open()
For example, the following code displays a message box, as shown in Figure 12-5.
Figure 12-5
MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.YES | SWT.NO | SWT.CANCEL); messageBox.setText("Warning"); messageBox.setMessage("Save the changes before exiting?"); int buttonID = messageBox.open(); switch(buttonID) { case SWT.YES: // saves changes ... case SWT.NO: // exits here ... break; case SWT.CANCEL: // cancels the action ... }
First, a message box is created with a warning icon and three buttons. Then, we set the title and the message for this message box. The message box is displayed when the open method is called. After the user presses one of buttons, the message box is disposed of and the ID of the button being clicked is returned. We then take proper actions based on the returned value.
Sometimes, a message box is disposed of when the user presses the Esc key or clicks the close trim box(i.e., the box with an X at the upper right of the shell) of the dialog instead of clicking any of the buttons. In this case, the returned value is dependent on the button group specified. If there is a SWT.CANCEL button in the group, then SWT.CANCEL is returned. If there is only one button, i.e, SWT.OK, then the returned value is SWT.OK.
If none of the standard SWT dialogs satisfies your requirements, you can create your own dialogs. In Chapter 5, you learned how to create a dialog shell. To make dialog shells reusable, put dialog shells in classes implementing the Dialog class. The Dialog class is declared abstract, but there is no abstract method in it.
You use the following code to implement a number input dialog, as shown in Figure 12-6:
Figure 12-6
public class NumberInputDialog extends Dialog { Double value ; // the value to be returned. /** * @param parent */ public NumberInputDialog(Shell parent) { super(parent); } /** * @param parent * @param style */ public NumberInputDialog(Shell parent, int style) { super(parent, style); } /** * Makes the dialog visible. * * @return */ public Double open() { Shell parent = getParent(); final Shell shell = new Shell(parent, SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL); shell.setText("NumberInputDialog"); shell.setLayout(new GridLayout(2, true)); Label label = new Label(shell, SWT.NULL); label.setText("Please enter a valid number:"); final Text text = new Text(shell, SWT.SINGLE | SWT.BORDER); final Button buttonOK = new Button(shell, SWT.PUSH); buttonOK.setText("Ok"); buttonOK.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); Button buttonCancel = new Button(shell, SWT.PUSH); buttonCancel.setText("Cancel"); text.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { try { value = new Double(text.getText()); buttonOK.setEnabled(true); } catch (Exception e) { buttonOK.setEnabled(false); } } }); buttonOK.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { shell.dispose(); } }); buttonCancel.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { value = null; shell.dispose(); } }); // Prevents ESCAPE from disposing the dialog shell.addListener(SWT.Traverse, new Listener() { public void handleEvent(Event event) { if(event.detail == SWT.TRAVERSE_ESCAPE) event.doit = false; } }); text.setText(""); shell.pack(); shell.open(); Display display = parent.getDisplay(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } return value; } }
The open method first creates all the widgets needed. The dialog class should take care of data validation. To do that, you add a text modify listener to enable the OK button if the input is valid or to disable the button in case of invalid input. When any of the buttons is selected, the dialog should be disposed. If the Cancel button is selected, you set the value to null before disposing of the dialog. To force the user to click one of the buttons, you add a traverse listener to prevent escape from disposing of the dialog. At the end of the open method, you set up an event loop to prevent the method from returning immediately (for more details, see Chapter 4).
The open method returns the input number as a Double object or null if the user clicks the Cancel button. The code that follows is the sample usage of the NumberInputDialog class:
public static void main(String[] args) { Shell shell = new Shell(); NumberInputDialog dialog = new NumberInputDialog(shell); System.out.println(dialog.open()); }
Now, you have created a custom dialog and you can use it to get input from the user.
This chapter covered dialogs that are available in SWT packages. The chapter covered the general configuration and usage of dialogs, and I discussed each type of dialog. You use ColorDialog to enable the user to select a color and FontDialog to enable the user to select a font with font style, size, and effects. A sample application showed you how to use ColorDialog and FontDialog. To let the user select a file or directory, you use FileDialog or Directory, respectively. You use MessageBox to inform or warn the user. Finally, if none of the dialogs satisfies your needs, you can create your own dialog by extending the Dialog class.
Part I - Fundamentals
Part II - Design Basics
Part III - Dynamic Controls
Part IV - Application Development