简体   繁体   English

如何在用户点击JDialog之外时关闭模态JDialog?

[英]How to close a modal JDialog when user clicks outside of JDialog?

I have a Undecorated Modal JDialog which I want to setVisible(false) when the user clicks outside of the modal dialog. 我有一个Undecorated Modal JDialog,我想在用户点击模态对话框之外时设置为Visible(false)。

Is this possible in Swing? 这可能在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" 记住调用setVisible(true)时的模态块,所以你不能只说“不要使用模态对话框”

And I've tried focus listeners on the dialog, they don't trigger when its modal. 我已经尝试在对话框上集中监听器,它们的模态不会触发。

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. 编辑: 更改为使用WindowFocusListener而不是FocusListener,以及检查丢失焦点上的降序组件,以便在子组件获得焦点时不隐藏。

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);                
            }
        });
    }
}

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. 所有答案都是正确的,您应该创建一个非模态对话框,然后通过FocusListener处理您的用例。

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) {
    }
});

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

Not really a modal dialog then if clicking else where closes it, maybe you want setAlwaysOnTop 不是真正的模态对话框然后如果单击其他关闭它,也许你想要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);

Probably add a FocusListener and hide the dialog when it looses the focus. 可能会添加一个FocusListener并在失去焦点时隐藏该对话框。 May be tricky if some elements in the dialog can have focus. 如果对话框中的某些元素可以具有焦点,则可能会很棘手。 Anyways, experiment with it. 无论如何,试验它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM