WindowListener无法按预期工作

时间:2012-04-17 20:49:52

标签: java swing jframe listener

我希望我的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时会触发此方法吗?

3 个答案:

答案 0 :(得分:6)

对我而言,关键在于您希望通过更改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,同样没有具有绑定属性的类的知识。它们是完全分离的。

答案 1 :(得分:4)

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

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

答案 2 :(得分:2)

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

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