2009-11-04 1 views
5

У меня есть Undecorated Modal JDialog, который я хочу установить для Visible (false), когда пользователь щелкает за пределами модального диалога.Как закрыть модальный JDialog при нажатии пользователем вне JDialog?

Возможно ли это в Swing?

Что я делаю, это вытащить пользовательский редактор для текстового поля, такого как селектор даты. Есть ли более простой способ сделать то, что я хочу?

EDIT

Помните, что модальные блоки на призыв к SetVisible (правда), так что вы не можете просто сказать «не использовать модальный диалог»

И я пытался сосредоточиться слушатели в диалоговом окне, они не срабатывают, когда модальность.

+0

Вы пробовали метод addAWTEventListener, это должно дать вам события для всех указанных типов событий, например. в приведенном ниже примере это будут все события мыши. – vickirk

+0

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

ответ

3

Это не модальный диалог, если вы можете щелкнуть его, а «что-то» произойдет. Все ответы верны, вы должны создать немодальный диалог, а затем обработать свой прецедент через FocusListener.

+0

Это самый близкий ответ «Нет». Это все, что я просил. Не так, как я могу достичь этого без немодального диалога. – Pyrolistical

0

Не совсем модальный диалог, то если щелкнув еще где закрывает его, может быть, вы хотите 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); 
+0

Я только что протестировал это, и похоже, что этот слушатель также не получает никаких событий мыши вне модального диалога. – Zalumon

0

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

+0

Могут ли модальные диалоги (и дочерние компоненты) потерять фокус для чего угодно, кроме переключения на другое приложение? – vickirk

+0

Ах, получилось, что вы имеете в виду, вы имели в виду вместо модального диалога! Не знаю, почему это было отклонено. – vickirk

10

EDIT:Изменены использовать 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);     
      } 
     }); 
    } 
} 
+0

Фокус потерял бы, чтобы компонент, получивший фокус, не был дочерним компонентом диалога, поэтому вам нужно будет искать иерархию компонентов через 'getParent()' – vickirk

+0

@vickirk - - хорошая точка зрения. Я изменил приведенный выше пример, чтобы проверить компоненты-потомки (возможно, край, но я добавил пример, чтобы создать дочернее окно диалога). Я также изменил его, чтобы использовать прослушиватель фокуса окна. –

+0

Да, я полностью понимаю, как это можно сделать без модального диалога, но вопрос был в том, можно ли это сделать с помощью модального диалога. Основное преимущество использования модального диалога заключается в блокировке, когда setVisible (true). Моя цель состояла в том, чтобы не нужно было реструктурировать программу для использования немодального диалога или написать утилиту для эмуляции характера блокировки в немодальном диалоге. – Pyrolistical

0

Используйте WindowListener и обработайте событие windowDeactivated().

+0

Я только что протестировал это, и для меня этот подход, похоже, работал только при полном нажатии за пределы приложения java, но не при попытке щелкнуть по основному фрейму java, который породил модальный диалог. – Zalumon

+0

@ Zalumon, я думаю, этот ответ был не очень ясен. Это было предложение НЕ использовать модальный JDialog. Когда вы используете модальный JDialog в качестве всплывающего окна, вы не можете закрыть диалоговое окно, если вы щелкните за пределами диалогового окна. Это решение, позволяющее закрыть «немодальное диалоговое окно», когда вы выходите за пределы области диалога, поэтому «всплывающее диалоговое окно» закрывается. – camickr

1

Не обязательно быть модальным диалоговым окном (модальное означает, что оно не позволяет вам использовать окно владельца, пока вы не скроете диалог). Лучше попробовать это:

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

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

Пытаться установить режимные ложь, а затем использовать windowsDeactivated() для близкого де диалога (dialog.dispose()), работает для меня.

 Смежные вопросы

  • Нет связанных вопросов^_^