setModal issue with 2 Jdialogs within a Jframe

后端 未结 1 1714
忘了有多久
忘了有多久 2021-01-24 13:17

I am facing issues when I set my first JDialog modal and the second one non-modal.

This is the functionality I am trying to implement:

  1. On clic
相关标签:
1条回答
  • 2021-01-24 13:45

    I even tried to set CustomDialogSearch's parent to be CustomDialog the behaviour still not correct.

    I think you're in the right track here but you need to play with dialogs modality type. For instance:

    • Set the modality type of Custom Dialog Main ("parent" dialog) as Dialog.ModalityType.APPLICATION_MODAL. By doing this when this dialog is visible it will block all windows except its children.
    • Set the modality type of Custom Dialog Search ("child" dialog) as Dialog.ModalityType.MODELESS. This way it won't block any other window and you can go from the child to the parent and vice versa.

    For a better understanding take a look to How to Use Modality in Dialogs article.

    Example

    Here is a code example about using modality as I've suggested above:

    import java.awt.Dialog;
    import java.awt.Window;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    
    public class Demo {
    
        private void createAndShowGUI() {
            JButton button = new JButton("Create Parent modal dialog");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton button = (JButton)e.getSource();
                    JFrame owner = (JFrame)SwingUtilities.windowForComponent(button);
                    Demo.this.createAndShowParentDialog(owner);                
                }
            });
    
            JFrame frame = new JFrame("Demo");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(button);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        private void createAndShowParentDialog(JFrame owner) {
            JButton button = new JButton("Create Child non-modal dialog");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton button = (JButton)e.getSource();
                    JDialog parent = (JDialog)SwingUtilities.windowForComponent(button);
                    Demo.this.createAndShowChildrenDialog(parent);                
                }
            });
    
            JDialog parentDialog = new JDialog(owner, "Parent dialog");
            parentDialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
            parentDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            parentDialog.getContentPane().add(button);
            parentDialog.pack();
            parentDialog.setLocationRelativeTo(null);        
            parentDialog.setVisible(true);
        }
    
        private void createAndShowChildrenDialog(JDialog parent) {        
            JButton backButton = new JButton("Back to parent dialog");
            backButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton button = (JButton)e.getSource();
                    Window dialog = SwingUtilities.windowForComponent(button);
                    dialog.getOwner().toFront();
                }
            });
    
            JDialog childDialog = new JDialog(parent, "Child dialog");
            childDialog.setModalityType(Dialog.ModalityType.MODELESS);
            childDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            childDialog.getContentPane().add(backButton);
            childDialog.pack();
            childDialog.setLocationRelativeTo(null);        
            childDialog.setVisible(true);
        }
    
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Demo().createAndShowGUI();
                }
            });
        }    
    }
    

    Edit

    I can select the windows of parent and child JDialogs but when I select the parent JDialog window, the child JDialog is still in front of parent JDialog.

    Well I have a better understanding now on what is the problem. This behaviour depends on how native windowing system handles focused and active windows. Having said this if you call for instance toFront() it will attempt to place the window at the top of the stack BUT some platforms do not allow windows which own other windows to appear on top of its childre. The same happens when you call toBack() method. See the javadocs for more details.

    I've tested my code on Windows 7 (32 bits if it makes any difference) and parent dialog becomes focused but its children still showing (not focused) at the top. As mentioned above it's up to the windowing system decide how to handle this matter.

    0 讨论(0)
提交回复
热议问题