WindowListener无法按预期工作

我希望我的GUI在出现JOptionPane时进行一些检查。 因为我找不到任何其他方式,我虽然每次应用程序窗口失去焦点时都可以执行这些操作(它只是检查字符串)。 出于这个原因,我在我的JFrame上添加了以下代码:

appFrame.addWindowListener(new WindowAdapter() { @Override public void windowLostFocus(WindowEvent e) { System.out.println("Focus Lost"); } @Override public void windowClosing(WindowEvent e) { //some other stuff here that work } }); 

关闭窗口的监听器工作正常。 虽然当JFrame没有集中时没有任何反应。 每次从JFrame切换到其他窗口时,不应该打印“Focus Lost”吗? 此外,当显示JOptionPane时是否会触发此方法?

我不打算讨论你为什么要做你正在做的事情,但由于以下原因,它没有像你期望的那样工作:

WindowAdapter是一个便利类,因此您可以创建一个侦听器并为多种类型的事件注册它。 您只为一组事件注册了它,您还需要通过以下方式注册焦点事件: Window.addWindowFocusListener()

 WindowAdapter adapter = new WindowAdapter() { @Override public void windowLostFocus(WindowEvent e) { System.out.println("Focus Lost"); } @Override public void windowClosing(WindowEvent e) { //some other stuff here that work } }; appFrame.addWindowListener(adapter); appFrame.addWindowFocusListener(adapter); 

对我而言,关键在于您希望通过更改String变量触发GUI的更改。 我看到解决此问题的最佳方法是使用PropertyChangeListenerSupport使String变量成为绑定属性。 这样,您可以让GUI将PropertyChangeListener附加到包含String变量的类,然后在更改时通知您,以便适当地更新GUI。

如果你走这条路线,考虑给观察的类一个SwingPropertyChangeSupport字段,以便在Swing事件线程上通知监听器,并希望避免任何Swing并发问题。

这是一个简短的例子:

 import java.awt.Dimension; import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.SwingPropertyChangeSupport; public class ShowPropertyChangeSupport { @SuppressWarnings("serial") private static void createAndShowGui() { final MainGUI mainGui = new MainGUI("Title"); final ObservedClass observedClass = new ObservedClass(); observedClass.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent pcEvt) { if (pcEvt.getPropertyName().equals(ObservedClass.BOUND_PROPERTY)) { mainGui.setTitle(pcEvt.getNewValue().toString()); } } }); mainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainGui.pack(); mainGui.setLocationRelativeTo(null); mainGui.setVisible(true); int timerDelay = 6000; // every 6 seconds new Timer(timerDelay, new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { String result = JOptionPane.showInputDialog(mainGui, "Please enter a String", "Set GUI title", JOptionPane.PLAIN_MESSAGE); if (result != null) { observedClass.setBoundProperty(result); } } }){{setInitialDelay(1000);}}.start(); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } // ** note that I don't like extending JFrame, // but will do this for sake of example simplicity class MainGUI extends JFrame { public MainGUI(String title) { super(title); } @Override public Dimension getPreferredSize() { return new Dimension(400, 300); } } class ObservedClass { public static final String BOUND_PROPERTY = "bound property"; private String boundProperty = ""; private SwingPropertyChangeSupport spcSupport = new SwingPropertyChangeSupport( this); public SwingPropertyChangeSupport getSpcSupport() { return spcSupport; } public void setSpcSupport(SwingPropertyChangeSupport spcSupport) { this.spcSupport = spcSupport; } public String getBoundProperty() { return boundProperty; } public void setBoundProperty(String boundProperty) { String oldValue = this.boundProperty; String newValue = boundProperty; this.boundProperty = newValue; spcSupport.firePropertyChange(BOUND_PROPERTY, oldValue, newValue); } public void addPropertyChangeListener(PropertyChangeListener listener) { spcSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { spcSupport.removePropertyChangeListener(listener); } } 

在我看来,所有这一切的关键是使用监听器,以便具有绑定属性的类 – 被监听的字符串 – 不知道GUI,监听器和GUI,同样不知道具有bound属性的类。 它们完全分离。

1) JOptionPane / modal JDialog有模态问题,但是如果所有容器都拥有自己的所有者,模态可能是有利的,对于你需要知道的真正的解决方法(我将谈论我该如何测试)

  • Window[] ,如果isDisplayable() ,则可以使用以下

  • 你可以得到SwingUtilities#getAccessibleIndexInXxx可以返回AccessibleState

  • KeyboardFocusManager (非常有趣的多点触控方法)返回getXxxFocusXxx方法

  • Focus,FocusSubsystem非常异步,

2)请充分尊重,我不知道为什么你需要这个,为什么我需要知道的原因,有关于业务规则,你总是需要知道….,如果在EDT上完成

  • Focus,FocusSubsystem非常异步,