java 如何制作 setVisible 块的非模态对话框?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6895265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 17:47:33  来源:igfitidea点击:

How do I make non-modal dialog whose setVisible blocks?

javaswingdialogvisibilityblocking

提问by Joonas Pulakka

In a Swing (J)Dialog, setModalsets the modality - that is, whether the dialog should block input to other windows or not. Then, setVisibledocs say for modal dialogs:

在 Swing (J)Dialog 中,setModal设置模态 - 即对话框是否应阻止对其他窗口的输入。然后,setVisible文档说模态对话框

If the dialog is not already visible, this call will not return until the dialog is hidden by calling setVisible(false) or dispose.

如果对话框不可见,则在通过调用 setVisible(false) 或 dispose 隐藏对话框之前,此调用不会返回。

Indeed, setVisibledoesreturn right away if the dialog is not modal. Sample code:

事实上,如果对话框不是模态的,setVisible它会立即返回。示例代码:

JDialog jd = new JDialog();
jd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

/**
 * If set to false, setVisible returns right away.
 * If set to true, setVisible blocks until dialog is disposed.
 */
jd.setModal(false);

System.out.println("setting visible");
jd.setVisible(true);
System.out.println("set visible returned");

I want to make a dialog that doesn'tblock input to other windows, but still doesblock the caller. What is a good way to do this, now that setVisibledoesn't block when the dialog is not modal?

我想制作一个不会阻止对其他窗口的输入的对话框,但仍然阻止调用者。这样做的好方法是什么,现在setVisible当对话框不是模态时不会阻塞?

Is there some rationale whysetVisible's behavior depends on the modality?

是否有一些理由为什么setVisible's 的行为取决于模式?

回答by perp

I need to make a dialog that doesn't block input to other windows, but does block the caller so that I know when the dialog has been closed.

我需要创建一个对话框,它不会阻止对其他窗口的输入,但会阻止调用者,以便我知道对话框何时关闭。

I usually solve this not by blocking the caller, but by using a callback of some sort - a simple interface that the dialog invokes when it's done. Let's say your dialog has an "OK" and a "Cancel" button and you need to distinguish which one is pressed. Then you could do something like this:

我通常不是通过阻止调用者来解决这个问题,而是通过使用某种回调 - 一个简单的界面,对话框在完成时调用。假设您的对话框有一个“确定”和一个“取消”按钮,您需要区分按下了哪个按钮。然后你可以做这样的事情:

public interface DialogCallback {
    void ok();
    void cancel();
}

public class MyModelessDialog extends JDialog {
    private final DialogCallback cbk;
    private JButton okButton, cancelButton;        

    public MyModelessDialog(DialogCallback callback) {
        cbk = callback;
        setModalityType(ModalityType.MODELESS);

        okButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onOK();
            }
        };

        cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        };

        // Treat closing the dialog the same as pressing "Cancel":
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e)  {
                onCancel();
            }
        };
    }

    private void onOK() {
        cbk.ok();
    }

    private void onCancel() {
        cbk.cancel();
    }
}

Then you just pass in an instance of DialogCallback to the constructor:

然后你只需将 DialogCallback 的实例传递给构造函数:

MyModelessDialog dlg = new MyModelessDialog(new DialogCallback() {
    public void onOK() { 
        // react to OK
    }
    public void onCancel() { 
        // react to Cancel
    }
 });

EDIT

编辑

Is there some rationale why setVisible's behavior depends on the modality?

为什么 setVisible 的行为取决于模式有什么理由吗?

Well, that's just how how modalwindows are supposed to work, no? A modal window shouldblock the current workflow when displayed, and a non-modal/modeless should not. See e.g. the Wikipedia pages on modal windowsor dialog boxes.

嗯,这就是模态窗口应该如何工作,不是吗?模态窗口在显示时应阻止当前工作流,而非模态/无模式不应。参见例如关于模态窗口对话框的维基百科页面。

回答by Noman_1

Just put this.setModal(true)but not set the parent dialog on the constructor:

只需this.setModal(true)在构造函数上放置但不设置父对话框:

MyDialog dlg = new JDialog();

MyDialog dlg = new JDialog();

this.setModal(true);

this.setModal(true);

When you call setVisible(true), it wont stop

当你打电话时setVisible(true),它不会停止

回答by Karthi

The direct approach is by:

直接的方法是:

JDialog dialog = new JDialog(owner, ModalityType.DOCUMENT_MODAL);

回答by JC Wouters

I have found another way to do this. In the constructor of my progress bar, which extends javax.swing.JDialog, I added:

我找到了另一种方法来做到这一点。在我的进度条的构造函数中,它扩展了 javax.swing.JDialog,我添加了:

setModalityType(ModalityType.APPLICATION_MODAL);

I then overrode the setVisible method:

然后我覆盖了 setVisible 方法:

@Override
public void setVisible(boolean b) {
    if (b) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                showProgress();
            }
        }).start();
    } else {
        super.setVisible(false);
    }
}

In the run(), you can see a call to showProgress(). This simply is:

在 run() 中,您可以看到对 showProgress() 的调用。这简直是​​:

public void showProgress() {
    super.setVisible(true);
}

What happens here, is the setVisible() method of JDialog blocks. So I overrode it, and called setVisible() of the JDialog, in a thread. Resulting in it not blocking.

这里发生的是 JDialog 块的 setVisible() 方法。所以我覆盖了它,并在一个线程中调用了 JDialog 的 setVisible()。导致它没有阻塞。