EDIT:modificata per utilizzare WindowFocusListener invece di focusListener, oltre che di controllo per la discesa dei componenti sul fuoco persa al fine di non nascondere se un componente bambino viene attivato.
Un modo semplice sarebbe aggiungere un listener di messa a fuoco finestra nella finestra di dialogo che lo nasconde quando si perde lo stato attivo. In questo caso, non vedo la necessità di una modalità. Ad esempio:
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);
}
});
}
}
fonte
2009-11-04 19:50:20
Hai provato il metodo addAWTEventListener, questo dovrebbe fornire eventi per tutti i tipi di eventi specificati, ad es. nell'esempio che ho fornito di seguito, si tratterà di tutti gli eventi del mouse. – vickirk
So che hai detto "quindi non puoi semplicemente dire" non usare una finestra di dialogo modale "", presumibilmente perché hai un codice che viene eseguito subito dopo la chiamata setVisible? Non potresti spostare questo in forse un ascoltatore per quando il dialogo è chiuso? Senza conoscere i dettagli della tua app, può fornire un design più pulito, specialmente quando si tratta di test delle unità, mi piace spostare i dialoghi in una strategia per ottenere risposte degli utenti, in modo da poter iniettare strategie fittizie senza appendere un test unitario quando viene eseguito senza testa o senza dover scherzare con la creazione di eventi programmaticamente. – vickirk