Search code examples
javaswingjdialogwindowbuilder

Dispose JDialog from another class


I want to dispose a JDialog from another class, because i am trying to keep classes and methods clean, and not create buttons and handle the listeners in the same class. So here is the problem.

I tried creating a get method from the first class to get the dialog and then dispose it on the third but didnt work.

public class AddServiceListener extends JFrame implements ActionListener {

/**
 * Creates listener for the File/New/Service button.
 */
public AddServiceListener() {

}

/**
 * Performs action.
 */
public void actionPerformed(ActionEvent e) {    
    AddServiceWindow dialog = new AddServiceWindow();
    dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    dialog.setVisible(true);
}
}


public class AddServiceWindow extends JDialog {

private JPanel contentPanel;
private JFrame frame;
private JPanel buttonPanel;
private JLabel nameLabel;
private JTextField nameField;
private JLabel destinationLabel;
private JTextField destinationField;
private JButton destinationButton;
private JButton okButton;
private JButton cancelButton;

/**
 * Creates the dialog window.
 */
public AddServiceWindow() {
    ManageMinder mainFrame = new ManageMinder();
    frame = mainFrame.getFrame();

    contentPanel = new JPanel();
    contentPanel.setLayout(null);

    setTitle("New Service File");
    setSize(340, 220);
    setLocationRelativeTo(frame);
    getContentPane().setLayout(new BorderLayout());
    contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
    getContentPane().add(contentPanel, BorderLayout.CENTER);

    buttonPanel = new JPanel();
    buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
    getContentPane().add(buttonPanel, BorderLayout.SOUTH);

    createLabels();
    createTextFields();
    createButtons();
    addListeners();
}

/**
 * Creates the labels.
 */
private void createLabels() {
    nameLabel = new JLabel("Name:");
    nameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
    nameLabel.setBounds(25, 25, 52, 16);
    contentPanel.add(nameLabel);

    destinationLabel = new JLabel("Path:");
    destinationLabel.setHorizontalAlignment(SwingConstants.RIGHT);
    destinationLabel.setBounds(7, 70, 70, 16);
    contentPanel.add(destinationLabel);
}

/**
 * Creates the text fields.
 */
private void createTextFields() {
    nameField = new JTextField();
    nameField.setBounds(87, 22, 220, 22);
    contentPanel.add(nameField);
    nameField.setColumns(10);

    destinationField = new JTextField();
    destinationField.setBounds(87, 68, 220, 20);
    contentPanel.add(destinationField);
    destinationField.setColumns(10);
}

/**
 * Creates the buttons of the window.
 */
private void createButtons() {  
    destinationButton = new JButton("Select...");
    destinationButton.setBounds(87, 99, 82, 23);
    destinationButton.setFocusPainted(false);
    contentPanel.add(destinationButton);

    okButton = new JButton("OK");
    okButton.setFocusPainted(false);
    buttonPanel.add(okButton);

    cancelButton = new JButton("Cancel");
    cancelButton.setFocusPainted(false);
    buttonPanel.add(cancelButton);
}

/**
 * Adds listeners to buttons.
 */
private void addListeners() {       
    ActionListener destinationAction = new AddDestinationListener(destinationField);
    destinationButton.addActionListener(destinationAction);

    ActionListener okAction = new SaveNewServiceFileListener(nameField, destinationField);
    okButton.addActionListener(okAction);
}
}


public class SaveNewServiceFileListener extends JFrame implements ActionListener {

private JTextField nameField;
private JTextField destinationField;
private String path;
private File newService;

/**
 * Creates listener for the File/New/Add Service/OK button.
 */
public SaveNewServiceFileListener(JTextField nameField, JTextField destinationField) {
    this.nameField = nameField;
    this.destinationField = destinationField;
}

/**
 * Performs action.
 */
public void actionPerformed(ActionEvent e) {
    path = destinationField.getText() + "\\" + nameField.getText() + ".csv";

    try {
        newService = new File(path);
        if(newService.createNewFile()) {
            System.out.println("Done!");
            // DISPOSE HERE
        }
        else {
            System.out.println("Exists!");
        }
    } catch (IOException io) {
        throw new RuntimeException(io);
    }
}
}

What should i do, so the dialog disposes on the third one, when OK is clicked and file is created?


Solution

  • The way to change the state of another object is to 1) have a reference to that object, and 2) call a public method on it.

    Here the other object is the JDialog, and the state that you wish to change is its visibility by calling either .close() or .dispose() on it. The problem that you're having is that the reference to the JDialog is not readily available since it is buried within the actionPerformed(...) method of your AddServiceListener class.

    So don't do this -- don't bury the reference but rather put it into a field of the class that needs it.

    If you absolutely need to have stand-alone ActionListener classes, then I think that the simplest thing to do is to take the dialog out of the listener class and into the view class, your main GUI, and then have the listener call methods on the view. For example

    Assume that the dialog class is called SomeDialog and the main GUI is called MainGui. Then put the reference to the dialog in the MainGui class:

    public class MainGui extends JFrame {
        private SomeDialog someDialog = new SomeDialog(this);
    

    And rather than have your listeners create the dialog, have them call a method in the main class that does this:

    public class ShowDialogListener implements ActionListener {
        private MainGui mainGui;
    
        public ShowDialogListener(MainGui mainGui) {
            // pass the main GUI reference into the listener
            this.mainGui = mainGui;
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            // tell the main GUI to display the dialog
            mainGui.displaySomeDialog();
        }
    }
    

    Then MainGUI can have:

    public void displaySomeDialog() {
        someDialog.setVisible(true);
    }
    

    An example MRE program could look like so:

    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Window;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    public class FooGui002 {
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> {
                MainGui mainGui = new MainGui();
                mainGui.setVisible(true);
            });
        }
    }
    
    @SuppressWarnings("serial")
    class MainGui extends JFrame {
        private SomeDialog someDialog;
        private JButton showSomeDialogButton = new JButton("Show Some Dialog");
        private JButton closeSomeDialogButton = new JButton("Close Some Dialog");
    
        public MainGui() {
            super("Main GUI");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setPreferredSize(new Dimension(500, 200));
    
            someDialog = new SomeDialog(this);
    
            showSomeDialogButton.addActionListener(new ShowDialogListener(this));
            showSomeDialogButton.setMnemonic(KeyEvent.VK_S);
    
            closeSomeDialogButton.addActionListener(new CloseSomeDialogListener(this));
            closeSomeDialogButton.setMnemonic(KeyEvent.VK_C);
    
            setLayout(new FlowLayout());
            add(showSomeDialogButton);
            add(closeSomeDialogButton);
            pack();
            setLocationByPlatform(true);
        }
    
        public void displaySomeDialog() {
            someDialog.setVisible(true);
        }
    
        public void closeSomeDialog() {
            someDialog.setVisible(false);
        }
    }
    
    @SuppressWarnings("serial")
    class SomeDialog extends JDialog {
        public SomeDialog(Window window) {
            super(window, "Some Dialog", ModalityType.MODELESS);
            setPreferredSize(new Dimension(300, 200));
            add(new JLabel("Some Dialog", SwingConstants.CENTER));
            pack();
            setLocationByPlatform(true);
        }
    }
    
    class ShowDialogListener implements ActionListener {
        private MainGui mainGui;
    
        public ShowDialogListener(MainGui mainGui) {
            this.mainGui = mainGui;
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            mainGui.displaySomeDialog();
        }
    }
    
    class CloseSomeDialogListener implements ActionListener {
        private MainGui mainGui;
    
        public CloseSomeDialogListener(MainGui mainGui) {
            this.mainGui = mainGui;
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            mainGui.closeSomeDialog();
        }
    }