Как сделать немодальный диалог, чьи блоки setVisible? - PullRequest
2 голосов
/ 01 августа 2011

В диалоге Swing (J), setModal устанавливает модальность - то есть, должен ли диалог блокировать ввод в другие окна или нет. Затем setVisible документы говорят для модальных диалогов :

Если диалог еще не виден, этот вызов не вернется, пока диалог не будет скрыт с помощью вызова setVisible (false) или dispose.

Действительно, 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");

Я хочу создать диалоговое окно, в котором не блокирует ввод в другие окна, но все же блокирует вызывающую сторону. Каков хороший способ сделать это, теперь, когда setVisible не блокируется, когда диалог не модальный?

Есть ли какое-то обоснование , почему поведение setVisible зависит от модальности?

Ответы [ 4 ]

5 голосов
/ 01 августа 2011

Мне нужно создать диалог, который не блокирует ввод в другие окна, но блокирует вызывающую программу, чтобы я знал, когда диалог был закрыт.

Обычно я решаю эту проблему не путем блокировки вызывающей стороны, а с помощью какого-либо обратного вызова - простого интерфейса, который вызывается диалогом, когда это сделано. Допустим, в вашем диалоговом окне есть кнопка «ОК» и «Отмена», и вам нужно различить, какая из них нажата. Тогда вы могли бы сделать что-то вроде этого:

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

Затем вы просто передаете экземпляр DialogCallback конструктору:

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

EDIT

Есть ли какое-то обоснование, почему поведение setVisible зависит от модальности?

Ну, вот как именно модальные окна должны работать, нет? Модальное окно должно блокировать текущий рабочий процесс при отображении, а немодальное / немодальное не должно. Смотрите, например страницы Википедии в модальных окнах или диалоговых окнах .

0 голосов
/ 24 октября 2014

Я нашел другой способ сделать это. В конструкторе моего индикатора выполнения, который расширяет javax.swing.JDialog, я добавил:

setModalityType(ModalityType.APPLICATION_MODAL);

Затем я переопределил метод setVisible:

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

В run () вы можете увидеть вызов showProgress (). Это просто:

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

Что здесь происходит, так это метод setVisible () блоков JDialog. Поэтому я переопределил его и вызвал setVisible () из JDialog в потоке. В результате чего не блокируется.

0 голосов
/ 17 октября 2014

Прямой подход к:

JDialog dialog = new JDialog(owner, ModalityType.DOCUMENT_MODAL);
0 голосов
/ 11 января 2014

Просто поставьте this.setModal(true), но не устанавливайте родительский диалог в конструкторе:

MyDialog dlg = new JDialog();

this.setModal(true);

Когда вы звоните setVisible(true), это не остановит

...