Home > Blockchain >  Java Swing - JDialog Modal Issue
Java Swing - JDialog Modal Issue

Time:09-12

I'm working on a program with multiple JMenu Items that correspond to different user needs. I've assigned the respectable actions to them in my main frame. My problem is that the EditUsers Dialog is looping forever the previous JDialog(AddUserDialog, which is working properly and responds to being clicked, working as intended), therefore resulting in a freeze and termination from Eclipse. I'd like to thank any kind soul in advance that will help me in any way possible.

public class MainFrame extends JFrame implements ActionListener{
//------------------all variables and values have been assigned, JMenu Items are the focus------------
        users = new JMenu("Users");
        menuBar.add(users);
        
        addUsers = new JMenuItem("Add User");
        users.add(addUsers);
        addUsers.addActionListener(this);
        editUsers = new JMenuItem("Edit User");
        users.add(editUsers);
        editUsers.addActionListener(this);
        auditUsers = new JMenuItem("Audit User");
        users.add(auditUsers);
        auditUsers.addActionListener(this);

public void actionPerformed(ActionEvent ae) {
        // TODO Auto-generated method stub
        
        //example for ActionListener in the first JMenuItem, working
        if(ae.getSource() == interfaceOpt) {
            JOptionPane.showMessageDialog(null, "Test");
            System.out.println("Test");
        }
        //working
        else if(ae.getSource()==sql){
            System.out.println("Test1");
            
        }
        //working
        else if(ae.getSource()==addUsers) {
            try {
                AddUserDialog addDialog=new AddUserDialog();
                addDialog.setModalityType(ModalityType.APPLICATION_MODAL);
                addDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            }catch(Exception ex) {
                ex.printStackTrace();
            }
            
            System.out.println("Test2");
        }
-------------------------------------HERE IS THE ISSUE------------------------------------------
        //not working, forever-looping the AddUserDialog class 
        else if(ae.getSource()==editUsers) {
            
            try {
                EditUsers editDialog=new EditUsers();
                editDialog.setModalityType(ModalityType.APPLICATION_MODAL);
                editDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            }catch(Exception ex) {
                ex.printStackTrace();
            }
            System.out.println("Test3");
        }

My Screenshots for context (JMenu Users): JMenu Users

Clicking on Add User: Add User

And lastly I just have a CPU stuttering when I try to run the Edit User Option. (Therefore no screenshot)

Currently I am working with the class AddUserDialog:

public class AddUserDialog extends JDialog implements ActionListener{
    
    //a bunch of attributes
    //do stuff
    public AddUserDialog(){
    //construct staff
    }
}

The EditUsers class:

public class EditUsers extends AddUserDialog implements ActionListener{
    //do stuff
    public EditUsers{
    //construct stuff
    }
}

NOTE: The classes work properly on their own. If people are interested I'll share the contents of both classes and give a general glimpse on the purposes of my program.

CodePudding user response:

My example has a simple frame with two menu items. Each one possesses a distinct instance of a dialog. For you, read the comments in the code. I am sure you will need distinct dialog classes that must follow the pattern I am about to show in the code below

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;

public class JDialogDemo extends JFrame {
    
    public static void main (String[] args) {
        JDialogDemo frame = new JDialogDemo();
        
        JMenuBar menuBar = new JMenuBar();
        JMenu usersMenu = new JMenu("Users");
        menuBar.add(usersMenu);
        
        JMenuItem addUserItem = new JMenuItem("Add User");
        JMenuItem editUserItem = new JMenuItem("Edit User");
        
        // Each menu item has its own listener to handle events
        addUserItem.addActionListener(new MenuActionListener("Add User"));
        editUserItem.addActionListener(new MenuActionListener("Edit User"));
        
        usersMenu.add(addUserItem);
        usersMenu.add(editUserItem);
        
        frame.setJMenuBar(menuBar);
        frame.setBounds(100, 100, 600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
    
    /*
     * My example is very simplistic. If you need to have different (custom)
     * dialogs, each menu item must implement the class that wraps the 
     * dialog that pertains to it. For instance, you may have an "Add"
     * dialog and an "edit" dialog. Each one, should follow this pattern.
     */
    private static class MenuActionListener implements ActionListener {
        private String title;
        public MenuActionListener(String title) {
            this.title = title;
        }

        @Override
        public void actionPerformed (ActionEvent e) {
            final JOptionPane optionPane = new JOptionPane(title,
                JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION);
            
            JMenuItem menuItem = (JMenuItem)e.getSource();
            
            final JDialog dialog = new JDialog((JFrame)menuItem.getParent().getParent(), "Click a button", true);
            dialog.setContentPane(optionPane);
            dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
            optionPane.addPropertyChangeListener(
            new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent e) {
                    String prop = e.getPropertyName();

                    if (dialog.isVisible() 
                     && (e.getSource() == optionPane)
                     && (prop.equals(JOptionPane.VALUE_PROPERTY))) {
                        dialog.setVisible(false);
                    }
                }
            });
            dialog.pack();
            dialog.setVisible(true);
        }
    }
}

Also, you must keep in mind that, if the logic that is executed when you add a new user or edit an existing one is expensive, you will need to execute this logic OUTSIDE the UI thread. In fact, even if it isn't, it is a bad idea to execute background processes in the same thread used by Java Swing to deal with UI events. Therefore, you must execute these processes in the background. A convenient way to do this is by using SwingWorker threads. You may want to look into that and make sure your adding and editing user processes are handled in separate SwingWorker threads.

UPDATE:

This isn't also the best way to run a Swing application. You should use SwingUtilities#invokeLater() to "create and show" GUI. There are plenty examples out there on how to do this. You might even know how to do this yourself already. If you need help on this and wish me to update the code above, just let me know.

  • Related