当用户在 JDialog 外部单击时如何关闭模态 JDialog?

发布于 2024-08-10 05:28:15 字数 276 浏览 7 评论 0原文

我有一个未装饰的模态 JDialog,当用户在模态对话框外部单击时,我想将其 setVisible(false) 。

这在 Swing 中可能吗?

我正在做的是弹出一个文本字段的自定义编辑器,例如日期选择器。有没有更简单的方法来做我想做的事?

编辑

请记住,模式会阻止对 setVisible(true) 的调用,因此您不能只是说“不要使用模式对话框”

而且我尝试过将侦听器聚焦在对话框上,但它们不这样做当其模态时不触发。

I have a Undecorated Modal JDialog which I want to setVisible(false) when the user clicks outside of the modal dialog.

Is this possible in Swing?

What I am doing is popping up a custom editor for a text field like a date selector. Is there an easier way to do what I want?

EDIT

Remember that modal blocks on the call to setVisible(true), so you can't just say "don't use a modal dialog"

And I've tried focus listeners on the dialog, they don't trigger when its modal.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

溺ぐ爱和你が 2024-08-17 05:28:15

编辑: 更改为使用 WindowFocusListener 而不是 FocusListener,并检查失去焦点的降序组件,以便在子组件获得焦点时不隐藏。

一种简单的方法是在对话框上添加一个窗口焦点侦听器,当焦点丢失时将其隐藏。我认为在这种情况下不需要模态。例如:

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class ClickAwayDialog extends JDialog {

    public ClickAwayDialog(final Frame owner) {
        super(owner);
        JPanel pnl = new JPanel(new BorderLayout());
        pnl.add(new JLabel("Click outside this dialog in the parent frame to close it"), BorderLayout.NORTH);
        JButton btn = new JButton("Click Me");
        btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(ClickAwayDialog.this, "New Child Window");
            }
        });
        pnl.add(btn, BorderLayout.CENTER);
        this.setContentPane(pnl);
        this.pack();
        this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        this.setLocationRelativeTo(owner);
        this.setAlwaysOnTop(true);
        this.addWindowFocusListener(new WindowFocusListener() {

            public void windowGainedFocus(WindowEvent e) {
                //do nothing
            }

            public void windowLostFocus(WindowEvent e) {
                if (SwingUtilities.isDescendingFrom(e.getOppositeWindow(), ClickAwayDialog.this)) {
                    return;
                }
                ClickAwayDialog.this.setVisible(false);
            }

        });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame parent = new JFrame();
                parent.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
                parent.setSize(300, 300);
                parent.setLocationByPlatform(true);
                parent.setVisible(true);
                ClickAwayDialog dlg = new ClickAwayDialog(parent);
                dlg.setVisible(true);                
            }
        });
    }
}

EDIT: Changed to use WindowFocusListener instead of FocusListener, as well as check for descending components on the focus lost in order to not hide if a child component gains focus.

A simple way would be to add a window focus listener on the dialog that hides it when focus is lost. I don't see the need for modality in this case. For example:

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class ClickAwayDialog extends JDialog {

    public ClickAwayDialog(final Frame owner) {
        super(owner);
        JPanel pnl = new JPanel(new BorderLayout());
        pnl.add(new JLabel("Click outside this dialog in the parent frame to close it"), BorderLayout.NORTH);
        JButton btn = new JButton("Click Me");
        btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(ClickAwayDialog.this, "New Child Window");
            }
        });
        pnl.add(btn, BorderLayout.CENTER);
        this.setContentPane(pnl);
        this.pack();
        this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        this.setLocationRelativeTo(owner);
        this.setAlwaysOnTop(true);
        this.addWindowFocusListener(new WindowFocusListener() {

            public void windowGainedFocus(WindowEvent e) {
                //do nothing
            }

            public void windowLostFocus(WindowEvent e) {
                if (SwingUtilities.isDescendingFrom(e.getOppositeWindow(), ClickAwayDialog.this)) {
                    return;
                }
                ClickAwayDialog.this.setVisible(false);
            }

        });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame parent = new JFrame();
                parent.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
                parent.setSize(300, 300);
                parent.setLocationByPlatform(true);
                parent.setVisible(true);
                ClickAwayDialog dlg = new ClickAwayDialog(parent);
                dlg.setVisible(true);                
            }
        });
    }
}
知你几分 2024-08-17 05:28:15

如果您可以在对话框外部单击并发生“某些事情”,那么它就不是模式对话框。所有答案都是正确的,您应该创建一个非模式对话框,然后通过 FocusListener 处理您的用例。

It's not a modal dialog if you can click outside of it and "something" happens. All the answers are correct, you should be creating a non-modal dialog and then deal with your use case via a FocusListener.

荆棘i 2024-08-17 05:28:15

它不一定是模式对话框(模式意味着它会阻止您使用所有者窗口,直到您隐藏该对话框)。最好尝试一下这个:

final JDialog dlg ...
dlg.setModal(false);

dlg.addWindowFocusListener(new WindowFocusListener() {            
    public void windowLostFocus(WindowEvent e) {
        dlg.setVisible(false);
    }            
    public void windowGainedFocus(WindowEvent e) {
    }
});

It's not necessary to be a modal dialog (modal means that it prevents you from using the owner window until you hide the dialog). Better try this:

final JDialog dlg ...
dlg.setModal(false);

dlg.addWindowFocusListener(new WindowFocusListener() {            
    public void windowLostFocus(WindowEvent e) {
        dlg.setVisible(false);
    }            
    public void windowGainedFocus(WindowEvent e) {
    }
});
风尘浪孓 2024-08-17 05:28:15

尝试将模式设置为 false,然后使用 windowsDeactivated() 关闭对话框(dialog.dispose()),对我有用。

Try to set the modal to false, and then use windowsDeactivated() for close de dialog (dialog.dispose()), works for me.

行至春深 2024-08-17 05:28:15

使用 WindowListener 并处理 windowDeactivated() 事件。

Use a WindowListener and handle the windowDeactivated() event.

尴尬癌患者 2024-08-17 05:28:15

并不是真正的模态对话框,如果单击其他位置关闭它,也许您需要 setAlwaysOnTop

但是,类似下面的内容应该可以解决问题(未经测试)。请注意,我建议将代码移动到比提供的使用更好的设计中。

static JDialog dialog = ...

Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
    public void eventDispatched(AWTEvent e) {
        dialog.setVisible(false);

        SwingUtils.invokeLater(new Runnable(){
            public void run(){
                Toolkit.getDefaultToolkit().removeAWTEventListener(this);
            }
        });        
    }
}, AWTEvent.MOUSE_EVENT_MASK);

dialog.setVisible(true);

Not really a modal dialog then if clicking else where closes it, maybe you want setAlwaysOnTop

However, something like the following should do the trick (untested). Note, I would recommend moving the code into something better designed than use as provided.

static JDialog dialog = ...

Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
    public void eventDispatched(AWTEvent e) {
        dialog.setVisible(false);

        SwingUtils.invokeLater(new Runnable(){
            public void run(){
                Toolkit.getDefaultToolkit().removeAWTEventListener(this);
            }
        });        
    }
}, AWTEvent.MOUSE_EVENT_MASK);

dialog.setVisible(true);
那请放手 2024-08-17 05:28:15

可能添加一个 FocusListener 并隐藏对话框失去焦点。如果对话框中的某些元素可以获得焦点,则可能会很棘手。无论如何,尝试一下。

Probably add a FocusListener and hide the dialog when it looses the focus. May be tricky if some elements in the dialog can have focus. Anyways, experiment with it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文