2009-11-04 12 views
5

Mam niezdefiniowany modalny JDialog, który chcę ustawićVide (false), gdy użytkownik kliknie poza modalnym oknie dialogowym.Jak zamknąć modalny JDialog, gdy użytkownik kliknie poza JDialog?

Czy to możliwe w Swing?

To, co robię, to pojawianie się edytora niestandardowego dla pola tekstowego, na przykład selektora daty. Czy istnieje łatwiejszy sposób robienia tego, co chcę?

EDIT

Pamiętaj, że modalnych bloki na wezwanie do setVisible (prawda), więc nie można po prostu powiedzieć „nie używaj modalne okno”

a próbowałem skupić słuchaczy w oknie dialogowym, nie uruchamiają się, gdy są modalne.

+0

Czy wypróbowałeś metodę addAWTEventListener, powinno to dać ci zdarzenia dla wszystkich określonych typów zdarzeń, np. w podanym poniżej przykładzie będą to wszystkie zdarzenia myszy. – vickirk

+0

Wiem, że powiedziałeś "nie możesz po prostu powiedzieć" nie używaj modalnego okna dialogowego "", prawdopodobnie dlatego, że masz kod, który wykonuje się bezpośrednio po wywołaniu setVisible? Czy nie mógłbyś przenieść tego do słuchacza, gdy okno dialogowe jest zamknięte? Bez znajomości szczegółów twojej aplikacji może ona zapewnić czystszy projekt, szczególnie jeśli chodzi o testowanie jednostkowe, lubię przenosić dialogi do strategii uzyskiwania odpowiedzi użytkowników, w ten sposób mogę wstrzykiwać fałszywe strategie bez zawieszania testu jednostki, gdy działa bezgłowy lub bez kłopotów z programowaniem wydarzeń. – vickirk

Odpowiedz

3

To nie jest modalne okno dialogowe, jeśli możesz kliknąć poza nim i "coś" się dzieje. Wszystkie odpowiedzi są poprawne, powinieneś stworzyć niemodalne okno dialogowe, a następnie zająć się przypadkiem użycia za pomocą FocusListener.

+0

To jest najbliższa odpowiedź na "Nie". To wszystko, o co prosiłem. Nie w jaki sposób mogę to osiągnąć bez niemodalnego dialogu. – Pyrolistical

0

Naprawdę nie modalne okno dialogowe, a następnie, jeśli kliknięcie zamyka ją gdzie indziej, może chcesz setAlwaysOnTop

Jednak coś jak następuje powinno wystarczyć (niesprawdzone). Uwaga: Zaleciłbym przeniesienie kodu do czegoś lepiej zaprojektowanego niż użycie zgodnie z opisem.

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

Właśnie przetestowałem to i wygląda na to, że ten rodzaj słuchacza również nie dostaje żadnych zdarzeń myszy poza oknem modalnym. – Zalumon

0

Prawdopodobnie dodać FocusListener i ukryć okno, gdy traci ostrość. Może być trudne, jeśli niektóre elementy w oknie dialogowym mogą być skupione. W każdym razie, eksperymentuj z tym.

+0

Czy modalne okno dialogowe (i komponenty potomne) może skupić się na czymkolwiek innym niż na zmianie innej aplikacji? – vickirk

+0

Ah, masz to, co masz na myśli, miałeś na myśli zamiast modalnego dialogu! Nie wiem, dlaczego zostało to odrzucone. – vickirk

10

EDIT:Zmieniono używać WindowFocusListener zamiast FocusListener, a także czek na malejąco komponentów naciskiem utraconej aby nie ukrywać Jeżeli zyski elementów dziecko skupić.

Prostym sposobem byłoby dodanie detektora ogniskowania okna w oknie dialogowym, które ukrywa go po utracie ostrości. Nie widzę potrzeby modalności w tym przypadku. Na przykład:

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

Utrata ostrości musiałaby zapewnić, że komponent, który uzyskał fokus, nie jest elementem potomnym okna dialogowego, więc będziesz musiał przeszukać hierarchię komponentów za pomocą 'getParent()' – vickirk

+0

@vickirk - - Słuszna uwaga. Zmieniłem powyższy przykład, aby sprawdzić elementy potomne (prawdopodobnie w przypadku krawędzi, ale ulepszyłem przykład, aby umożliwić utworzenie okna podrzędnego okna dialogowego). Zmieniłem go również, aby użyć detektora ogniskowania okna. –

+0

Tak, całkowicie rozumiem, jak można to zrobić bez modalnego okna dialogowego, ale punktem pytania było, czy można to zrobić za pomocą modalnego okna dialogowego. Główną zaletą korzystania z modalnego okna dialogowego jest blokowanie, gdy setVisible (true). Moim celem było zrezygnowanie z restrukturyzacji programu w celu użycia niemodalnego okna dialogowego lub napisania narzędzia do emulowania natury blokującej w niemodalnym dialogu. – Pyrolistical

0

Użyj WindowListener i obsłużyć zdarzenie windowDeactivated().

+0

Po prostu przetestowałem to i dla mnie to podejście wydawało się działać tylko po kliknięciu całkowicie poza aplikacją java, ale nie przy próbie kliknięcia głównej klatki języka Java, która wywołała modalne okno dialogowe. – Zalumon

+0

@Zalumon, myślę, że ta odpowiedź nie była zbyt jasna. Była to sugestia, aby NIE używać modalnego JDialog. Kiedy używasz modalnego JDialog jako wyskakującego okienka, nie możesz zamknąć okna, jeśli klikniesz poza tym oknem dialogowym. Jest to rozwiązanie pozwalające zamknąć okno dialogowe "niemodalne" po kliknięciu poza obszarem okna dialogowego, więc "okno dialogowe" zostanie zamknięte. – camickr

1

Nie trzeba być dialogiem modalnym (modalny oznacza, że ​​uniemożliwia korzystanie z okna właściciela, dopóki nie ukryjesz okna dialogowego). Lepiej spróbuj tego:

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

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

Spróbuj ustawić modal false, a następnie użyć windowsDeactivated() ścisłej de oknie dialogowym (dialog.dispose()), pracuje dla mnie.

Powiązane problemy