Java: Make JOptionPane dialog resizable

When you want to quickly create several different kinds of dialogs using Java Swing, JOptionPane provides you with very easy means of doing so.You can layout the dialog, provide icons, specify the title, text, buttons, display your own components… But one thing which is missing is the ability to make these dialogs resizable. When you just want to display some static or dynamic text, it’s usually not an issue but when you have components you can interact width, sometimes it is very helpful to be able to let the user expand the dialog.

In order to get this functionality, you need to be able to set the “resizable” property of the created dialog to true. When you create the dialog in this way, it is not so easy since you do not a reference to the dialog:

JOptionPane.showMessageDialog(myFrame, myComponent);

This just brings up an information-message dialog containing your component without returning anything. So you need a way to get called with a reference to the dialog containing you component after it has been created. A nice way to do it is to add a HierarchyListener to your component. It will get Hierarchy Change Events in the following scenarios:

  • addition of an ancestor
  • removal of an ancestor
  • hierarchy made visible or displayable
  • hierarchy made invisible or undisplayable

You should add the listener before displaying the dialog and it will be called when added to the dialog and also when made visible.
In the Listener, you need to navigate from your component back to the containing dialog using SwingUtilities.getWindowAncestor:

Window window = SwingUtilities.getWindowAncestor(component);

In order to use setResizable, you need to cast it to a dialog (checking whether the ancestor is really a dialog is always a good idea even though you know it is):

if (window instanceof Dialog) {
	Dialog dialog = (Dialog) window;
	if (!dialog.isResizable()) {
		dialog.setResizable(true);
	}
}

The check for isResizable makes sure we do not set the property multiple times and maybe unnecessarily trigger events…

Here an example first wrapping your component in a scrollpane:

private void showDialog(Component frame, final Component component) {
	// wrap a scrollpane around the component
	JScrollPane scrollPane = new JScrollPane(component);
	// make the dialog resizable
	component.addHierarchyListener(new HierarchyListener() {
		public void hierarchyChanged(HierarchyEvent e) {
			Window window = SwingUtilities.getWindowAncestor(component);
			if (window instanceof Dialog) {
				Dialog dialog = (Dialog) window;
				if (!dialog.isResizable()) {
					dialog.setResizable(true);
				}
			}
		}
	});
	// display them in a message dialog
	JOptionPane.showMessageDialog(frame, scrollPane);
}

Leave a Reply

Your email address will not be published.