Modal Dialogs

You’ve probably experienced dialog boxes in Microsoft Windows, or some other windowing system.  Typically, you click on a menu item in the menu bar, or perhaps a button somewhere in the GUI of an application, and up comes a dialog box for you to interact with.

Most often, when one of these dialog boxes comes up, you find that you can only interact with it, and cannot interact with the rest of the application.  If you try to, say, click on the main window of your application while the dialog box is up, you’ll find that it doesn’t respond (except that the system may beep at you, to indicate that you’re trying to do something that isn’t allowed.   This kind of dialog box is called a modal dialog.

The idea is that the application wants you to supply the information requested in the dialog before you are allowed to do anything else in the program.  So it prevents you from interacting with the rest of the application, for that reason.

This is implemented by the call to show (or setVisible(true)) the dialog.  The system blocks on that call, and the call will not return until the dialog is dismissed (set non-visible).  A blocking call is one that does not return until the operation  it is blocking on is completed.  While the call is blocked, events (such as mouse clicks, keystrokes, etc.) that are intended for the rest of the application are prevented from being delivered.  Only those events which are intended for the dialog box are actually delivered.

Non-Modal (or Modeless) Dialogs

Sometimes, however, applications need to be able to bring up a dialog box and have it stay visible, while at the same time interacting with the rest of the application.   Some applications, such as sophisticated graphical editors like Adobe PhotoShop, operate with several dialogs visible at any given time.   In these applications, the user is expected to enter information into these dialogs to control what is happening during the design process.   To be useful, such dialogs need to be non-modal (sometimes known as modeless).  That is, they do not block on their show/setVisible(true) calls, and they do not prevent events from being delivered to the rest of the application.

JDialog Constructors

Several constructors for the JDialog class expect an argument, boolean modal, which specifies whether the JDialog will be brought up as a modal or non-modal dialog.   For those constructors which do not specify this argument, the default is modal.

The setModal() Method

JDialog also has a method:

public void setModal(boolean b)

(actually, JDialog inherits it from its superclass, Dialog)

You can call this method to change the modal setting for a JDialog on the fly, before showing the dialog.  Of course, once the dialog is visible, changing its modal setting does nothing until the dialog is dismissed and then shown again.

Example

Here’s an example of a non-modal dialog.  I’ve modified the AboutDialogTest class that I showed you earlier.  There is one tiny change that I’ve made (towards the bottom), where I’ve simply invoked a JDialog constructor that accepts a modal argument, and hard-coded it to specify non-modal (false):

package swingExamples;

import java.awt.Container;
import java.awt.FlowLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingConstants;

class AboutDialog extends JDialog
{
  public AboutDialog(JFrame parent)
  {
    super(parent, "AboutDialog", false); // Non-modal
    
    // Add components to the dialog's content pane
    Container contentPane = getContentPane();
    contentPane.setLayout(new FlowLayout());
    JLabel label = new JLabel(
            "AboutDialogTest V1", SwingConstants.CENTER);
    contentPane.add(label);
    label = new JLabel(
            "by Bryan J. Higgs", SwingConstants.CENTER);
    contentPane.add(label);
    label = new JLabel(
            "October, 2001", SwingConstants.CENTER);
    contentPane.add(label);
    
    setSize(150, 100);
  }
}

class AboutDialogFrame extends JFrame
{
  public AboutDialogFrame(String title)
  {
    setTitle(title);
    setSize(300, 200);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    
    // Create menu bar with menu
    JMenu fileMenu = new JMenu("File");
    fileMenu.add("New...");
    fileMenu.add("Open...");
    fileMenu.add("Save");
    fileMenu.add("Save As...");
    fileMenu.addSeparator();
    fileMenu.add("Quit");
    
    JMenu helpMenu = new JMenu("Help");
    JMenuItem aboutItem = new JMenuItem("About...");
    aboutItem.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ev)
      {
        launchAboutDialog();
      }
    }
    );
    helpMenu.add(aboutItem);
    
    JMenuBar menuBar = new JMenuBar();
    menuBar.add(fileMenu);
    menuBar.add(helpMenu);
    setJMenuBar(menuBar);
  }
  
  private void launchAboutDialog()
  {
    AboutDialog dialog = new AboutDialog(this);
    dialog.setVisible(true);
  }
}

public class AboutDialogNonModalExample
{
  public static void main(String[] args)
  {
    AboutDialogFrame frame = 
          new AboutDialogFrame("AboutDialogTest");
    frame.setVisible(true);
  }
}

It produces the following results:

As you can see, because the AboutDialog is now non-modal, you can create as many instances of it as you would like, because you can still interact with the application frame’s menu.