【问题标题】:How to create a modal JDialog on top of another modal JDialog如何在另一个模态 JDialog 之上创建模态 JDialog
【发布时间】:2012-06-26 17:57:54
【问题描述】:

我有一个模式设置对话框,它是一个 JDialog。在这个设置窗口中,我放置了一些组件,包括一个指向另一个模态设置对话框的按钮,该对话框也是一个 JDialog。我将它们制作为 JDialogs,因为这是我所知道的制作模态对话框的唯一方法。

问题是这样的:当我创建主设置对话框时,我必须在没有父框架或父框架的情况下构建 JDialog。由于我的主窗口是一个 JFrame,我可以将它传递给主设置对话框构造函数。但是当我想创建第二个模式设置对话框时,它应该将主设置对话框作为父级,我找不到获取 JDialog 的 (J)Frame 的方法。我确实想将该主设置对话框作为父级传递,以便第二个设置对话框在显示时以它为中心。假设第二个设置对话框没有用于传递位置的构造函数,只有 JDialog 的构造函数。

有没有办法获取 JDialog 的 (J)Frame? 我的设置中是否存在设计缺陷,我是否应该为这些设置对话框使用其他东西? (如果是这样,我应该如何使这些替代设置对话框成为模态?)

感谢您的帮助, 埃里克

更新: 谢谢大家的答案。他们让我明白,显然拥有一个 JDialog 的所有者并不是绝对必要的。我认为对话框需要这样做才能禁用所有者,直到对话框关闭,但显然该模式独立于所有者。我还注意到,即使有所有者,对话框仍然不会以所有者为中心,所以现在我的代码如下:

public class CustomDialog extends JDialog {
    public CustomDialog(String title) {
        setModal(true);
        setResizable(false);
        setTitle(title);

        buildGUI();
    }

    public Result showDialog(Window parent) {
        setLocationRelativeTo(parent);
        setVisible(true);
        return getResult();
    }
}

这也允许模态对话框中的模态对话框。

感谢您的帮助!

【问题讨论】:

  • 我不会让设置窗口成为任何东西的模式。如果他们在设置窗口中工作时需要使用该应用程序怎么办?这对我来说似乎非常严格。

标签: java swing user-interface modal-dialog jdialog


【解决方案1】:

1.请阅读The New Modality API in Java SE 6

2.有没有办法获取JDialog的(J)Frame?

Window ancestor = SwingUtilities.getWindowAncestor(this);

Window ancestor = (Window) this.getTopLevelAncestor();

【讨论】:

    【解决方案2】:

    不确定你到底有什么问题,但这里有一个关于如何拥有多个模式对话框的示例:

    import java.awt.BorderLayout;
    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.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class TestDialog {
    
        protected static void initUI() {
            JPanel pane = newPane("Label in frame");
            JFrame frame = new JFrame("Title");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(pane);
            frame.pack();
            frame.setVisible(true);
    
        }
    
        public static JPanel newPane(String labelText) {
            JPanel pane = new JPanel(new BorderLayout());
            pane.add(newLabel(labelText));
            pane.add(newButton("Open dialog"), BorderLayout.SOUTH);
            return pane;
        }
    
        private static JButton newButton(String label) {
            final JButton button = new JButton(label);
            button.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    Window parentWindow = SwingUtilities.windowForComponent(button);
                    JDialog dialog = new JDialog(parentWindow);
                    dialog.setLocationRelativeTo(button);
                    dialog.setModal(true);
                    dialog.add(newPane("Label in dialog"));
                    dialog.pack();
                    dialog.setVisible(true);
                }
            });
            return button;
        }
    
        private static JLabel newLabel(String label) {
            JLabel l = new JLabel(label);
            l.setFont(l.getFont().deriveFont(24.0f));
            return l;
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    initUI();
                }
            });
        }
    }
    

    【讨论】:

    • 不错,但为什么新的JDialog 是以阶梯方式打开的?
    • @zygimantus 那是直接调用dialog.setLocationRelativeTo(button)引起的
    【解决方案3】:

    现在是 2021 年,距问题发布大约 8.5 年,但早在 2012 年,到目前为止,最简单的解决方案是简单地创建 JDialog 并以 Dialog 作为所有者。 Java 有 5 constructors with a Dialog owner 提供,旁边有 5 个类似的 Frame 所有者和 5 个 Window 所有者。

    OP 可能面临的问题是 Netbeans 或其他 IDE 中 JDialog 的默认模板。 Netbeans (12.2) 将其作为新 JDialog Form... 的模板提供:

    public class NewJDialog extends javax.swing.JDialog {
    
        /**
         * Creates new form NewJDialog
         */
        public NewJDialog(java.awt.Frame parent, boolean modal) {
            super(parent, modal);
            initComponents();
        }
    

    您可以简单地将构造函数的签名更改为使用Dialog 作为所有者,而不是Frame 的默认选项:

    public class NewJDialog extends javax.swing.JDialog {
    
        /**
         * Creates new form NewJDialog
         */
        public NewJDialog(java.awt.Dialog parent, boolean modal) {
            super(parent, modal);
            initComponents();
        }
    

    你走了。

    【讨论】:

      猜你喜欢
      • 2013-11-06
      • 2010-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多