2012-04-17 55 views
3

我想讓我的GUI在出現JOptionPane時進行一些檢查。 因爲我找不到任何其他方式,所以我儘管每次應用程序窗口失去焦點時都可以執行這些操作(它只是檢查字符串)。出於這個原因,我在我的JFrame上添加了以下代碼:WindowListener無法正常工作

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切換到其他窗口時,是否不應打印「聚焦丟失」?此外,顯示JOptionPane時會觸發此方法嗎?

+0

這似乎是這樣做的向後方式。什麼觸發了optionPane顯示?爲什麼不在這個觸發器中調用這段代碼? – 2012-04-17 20:52:31

+0

當在應用程序的某個其他部分發現字符串重複時(與GUI沒有任何關係),會顯示JOptionPane。 從該JOptionPane中更改一個字符串,並且該更改需要反映在JFrame標題上。由於這些類不會與我通信,但通過窗口監聽器可以很容易地檢查這種變化。 – Giannis 2012-04-17 20:55:57

+0

也許說明操作系統在這裏很有用......我不確定Windows是否向窗口發送消息以告訴它不再處於活動狀態(或者如果JVM處理它) – SJuan76 2012-04-17 20:57:38

回答

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

完成類似於觀察者的事情,但這回答了我的問題:) – Giannis 2012-04-18 18:44:59

6

對我來說,關鍵是你想改變一個字符串變量觸發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

是的,或者更一般地說,應用程序需要它自己的事件隊列 - 一個註冊監聽器和派發事件的全局地方。有很多方法可以獲取,不知道是否有任何特定的情況。 – 2012-04-17 21:09:55

+0

非常感謝這段代碼,它非常有趣。我最終做了類似於觀察者模式的事情。我確定我將來需要這個。 – Giannis 2012-04-18 11:36:18

+0

@Giannis:這就是 - 觀察者模式,但有一點額外的窗飾,所以你基本上按我的建議做。祝你的項目好運! – 2012-04-18 14:29:49

2

1)JOptionPane /莫代爾JDialog已經得到形式的問題,但方式可能是優勢,如果所有的容器都得到了自己的老闆,真正的解決方法,你需要知道(我會談論我該怎麼做測試)

2)請與應有的尊重,我不知道爲什麼你需要的,爲什麼原因,我需要知道的是,有關於業務規則,你總是需要知道....,如果是在美國東部時間