Usually in a Swing application if I want to display JDialogs
to the user, I create them once and then reuse them.
Usually the main JFrame
has references to these JDialogs
.
Sometimes though I need to display a JDialog
from parts of code outside the JFrame class
.
Usually I make the JDialog
member variables (of JFrame
) public and either they are static or pass a reference of the JFrame
arround to be able to access the JDialog
.
It works but it seems messy to me.
I was wondering is there a standard design approach for something like this?
-
This question focuses on code design; can you elaborate on the intended application design? – trashgod Jul 03 '11 at 19:32
-
You mean it depends on the specific application?I thought that may be the way to get input from various places from components like `JDialogs` or `JFileChooses` would be uniform like there is for example MVC regardless of the application scope – Cratylus Jul 03 '11 at 19:33
-
I thought you might be asking about modality, which is application level. – trashgod Jul 04 '11 at 01:07
2 Answers
Either pass the JFrame instance to the helper classes which create new JDialog instances, or, if your application has a single frame, make this frame accessible from anywhere:
public class MyApp {
private static JFrame mainFrame;
public static JFrame getMainFrame() {
return MyApp.mainFrame;
}
public static void main(String[] args) {
// ...
MyApp.mainFrame = new JFrame();
// ...
}
}
I usually avoid reusing dialog instances: this makes the code more difficult to write (you need to take care of the previous state of the dialog), and it consumes memory to keep invisible dialog instances around.

- 678,734
- 91
- 1,224
- 1,255
-
Nizet:I have seen though that reusing dialogs makes the UI faster than recreating them.This is the case also for `JFilechooser` – Cratylus Jul 03 '11 at 19:40
My own philosophy is to make almost all fields private, including the dialog and only expose that which needs exposing, no more and no less. For instance if I have a JDialog called from another class and I get information from that dialog, I expose only the information via public getter methods, not the dialog itself.
Edit 1
Sorry for some gross over-kill and much longer than expected code, but this is kind of what I meant in an MVC sort of way and created in a great hurry:
import java.awt.*;
import java.awt.Dialog.ModalityType;
import java.awt.event.*;
import javax.swing.*;
public class DialogEg {
private static void createAndShowUI() {
JFrame frame = new JFrame("Dialog Eg");
MainPanel mainPanel = new MainPanel();
MainControl mainControl = new MainControl(frame);
mainControl.setMainPanel(mainPanel);
mainPanel.setControl(mainControl);
frame.getContentPane().add(mainPanel.getMainPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class MainPanel {
private JPanel mainPanel = new JPanel();
private JButton showDlgBtn = new JButton("Show Dialog");
private JTextField field = new JTextField(10);
private MainControl mainControl;
public MainPanel() {
mainPanel.add(showDlgBtn);
mainPanel.add(field);
field.setEditable(false);
showDlgBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (mainControl != null) {
mainControl.showDialog();
}
}
});
}
public void setControl(MainControl mainControl) {
this.mainControl = mainControl;
}
public void setFieldText(String text) {
field.setText(text);
}
public JPanel getMainPanel() {
return mainPanel;
}
}
class DialogPanel {
private static final String[] COMBO_DATA = {"", "one", "two", "three", "four"};
private JPanel dialogPanel = new JPanel();
private JComboBox combo = new JComboBox(COMBO_DATA);
public DialogPanel() {
dialogPanel.add(combo);
combo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Window window = SwingUtilities.getWindowAncestor(dialogPanel);
window.dispose();
}
});
}
public JPanel getDialogPanel() {
return dialogPanel;
}
public String getSelectedText() {
return combo.getSelectedItem() == null ? "" : combo.getSelectedItem().toString();
}
}
class MainControl {
private DialogPanel dlgPanel = new DialogPanel();
private MainPanel mainPanel;
private JFrame frame;
public MainControl(JFrame frame) {
this.frame = frame;
}
public void setMainPanel(MainPanel mainPanel) {
this.mainPanel = mainPanel;
}
public void showDialog() {
if (mainPanel != null) {
JDialog dialog = new JDialog(frame, "Dialog", ModalityType.APPLICATION_MODAL);
dialog.getContentPane().add(dlgPanel.getDialogPanel());
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
String text = dlgPanel.getSelectedText();
if (text != null) {
mainPanel.setFieldText(text);
}
}
}
}
The key here is that the MainPanel has no knowledge about the DialogPanel and visa-versa since it's all connected by the MainControl through the marvels of MVC.

- 283,665
- 25
- 256
- 373
-
But how do you display the `JDialog` if it is private from another class? – Cratylus Jul 03 '11 at 19:41
-
@Hovercraft:Thank you for the sample!I see that you do not reuse but do a `new JDialog` and then add the `dlgPanel.getDialogPanel()`. This is to avoid redrawing? – Cratylus Jul 03 '11 at 20:12
-
@user384706: I recreate the dialog here, but don't always do that. It could be held by the DialogPanel. I think what is most important is that the two GUI's are distinct, and only connected by the Control. – Hovercraft Full Of Eels Jul 03 '11 at 20:26
-
:I like your example.One last question though:I always thought that the controller does "business" processing and no UI stuff.In your example it also handles the jdialog stuff.May be my understanding on the separation of the role of the various components in MVC has been to strict – Cratylus Jul 05 '11 at 16:10