Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
395 views
in Technique[技术] by (71.8m points)

java - WindowListener does not work as expected

I want my GUI to make some checks when a JOptionPane appears. Because I can't find any other way, I though I can do those each time the application window loses focus(its just checking a string). For that reason I added the following code on my 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
            }
});

The window closing listener works fine. Although when the JFrame isn't focused nothing happens. Shouldn't "Focus Lost" be printed each time I switch from JFrame to some other window? Also, will this method be triggered when a JOptionPane is shown?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The key to me is that you want a change in the GUI triggered by a change of a String variable. The best way I see to solve this is to make the String variable a bound property by using PropertyChangeListenerSupport. This way you can have the GUI attach a PropertyChangeListener to the class that holds the String variable and then be notified when it changes allowing you to update the GUI appropriately.

If you go this route, consider giving the observed class a SwingPropertyChangeSupport field so that the listeners will be notified on the Swing event thread and hopefully avoid any Swing concurrency issues.

Here's a brief example:

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

}

The key to all this in my mind is to use the listener so that the class with the bound property -- the String being listened to -- has no knowledge of the GUI, the listener, and the GUI, likewise has no knowledge of the class with the bound property. They are fully decoupled.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...