並不是所有的事件處理都像按鈕點擊那樣簡單。在正規的程序中,往往希望用戶在確認沒有丟失所做工作之後再關閉程序。當用戶關閉框架時,可能希望彈出一個對話框來警告用戶沒有保存的工作有可能會丟失,只有在用戶確認之後才退出程序。
當程序用戶試圖關閉一個框架窗口時,JFrame對象就是WindowEvent的事件源。如果希望捕獲這個事件,就必須有一個適合的監聽器對象,並將它添加到框架的窗口監聽器列表中。
窗口監聽器必須是實現WindowListener接口的類的一個對象。在WindowListener接口中包含7個方法。當發生窗口事件時,框架將調用這些方法響應7個不同的事件。從它們的名字就可以得知其作用,唯一的例外是在Windows下,通常將iconified稱爲minimized。
public interface WindowListener extends EventListener {
/**
* Invoked the first time a window is made visible.
*/
public void windowOpened(WindowEvent e);
/**
* Invoked when the user attempts to close the window
* from the window's system menu.
*/
public void windowClosing(WindowEvent e);
/**
* Invoked when a window has been closed as the result
* of calling dispose on the window.
*/
public void windowClosed(WindowEvent e);
/**
* Invoked when a window is changed from a normal to a
* minimized state. For many platforms, a minimized window
* is displayed as the icon specified in the window's
* iconImage property.
* @see java.awt.Frame#setIconImage
*/
public void windowIconified(WindowEvent e);
/**
* Invoked when a window is changed from a minimized
* to a normal state.
*/
public void windowDeiconified(WindowEvent e);
/**
* Invoked when the Window is set to be the active Window. Only a Frame or
* a Dialog can be the active Window. The native windowing system may
* denote the active Window or its children with special decorations, such
* as a highlighted title bar. The active Window is always either the
* focused Window, or the first Frame or Dialog that is an owner of the
* focused Window.
*/
public void windowActivated(WindowEvent e);
/**
* Invoked when a Window is no longer the active Window. Only a Frame or a
* Dialog can be the active Window. The native windowing system may denote
* the active Window or its children with special decorations, such as a
* highlighted title bar. The active Window is always either the focused
* Window, or the first Frame or Dialog that is an owner of the focused
* Window.
*/
public void windowDeactivated(WindowEvent e);
}
在Java中,實現一個接口的任何類都必須實現其中的所有方法;在這裏,意味着需要實現7個方法。然而這裏如果我們只對名爲windowClosing的方法感興趣。當然,可以這樣定義實現這個接口的類:在windowClosing方法中增加一個對System.out.println("TerminatorListener--windowClosing");的調用,其它6個方法不做任何事情:
class TerminatorListener implements WindowListener {
public void windowClosing(WindowEvent e) {
System.out.println("TerminatorListener--windowClosing");
}
@Override
public void windowOpened(WindowEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowClosed(WindowEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowIconified(WindowEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowDeiconified(WindowEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowActivated(WindowEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowDeactivated(WindowEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
}
書寫6個沒有任何操作的方法代碼顯然是一種乏味的工作。鑑於簡化的目的,每個含有多個方法的AWT監聽器接口都配有一個適配器(adapter)類,這個類實現了接口中的所有方法,但每個方法沒有做任何事情。這意味着適配器類自動地滿足了Java實現相關監聽器接口的技術需求。可以通過擴展適配器類來指定對某些事件的響應動作,而不必實現接口中的每個方法(ActionListener這樣的接口只有一個方法,因此沒必要提供適配器類)。下面使用窗口適配器。首先定義一個WindowAdapter類的擴展類,其中包含繼承的6個沒有做任何事情的方法和一個覆蓋的方法windowClosing:
class TerminatorAdapter extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.out.println("TerminatorAdapter---windowClosing");
}
}
現在,可以將一個Terminator對象註冊爲事件監聽器:
WindowListener listenerAdapter = new TerminatorAdapter();
adapterFrame.addWindowListener(listenerAdapter);
只要框架產生了窗口事件,就會通過調用7個方法之中的一個方法將事件傳遞給listener對象,其中6個方法沒有做過任何事情;windowClosing方法調用System.exit(0)終止應用程序的執行。警告:如果在擴展適配器類時將方法名拼寫錯了,編譯器不會捕獲到這個錯誤。例如,如果在WindowAdapter類中定義一個windowIsClosing方法,就會得到一個包含8個方法的類,並且windowClosing方法沒有做任何事情。
創建一個擴展於WindowAdapter的監聽器類是一個很好的改進,但是還可以繼續改進。事實上,沒有必要爲listener對象命名。只需寫成:
adapterFrame.addWindowListener(new WindowAdapter());
不要就此止步!我們可以將監聽器類定義爲框架的匿名內部類。adapterFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("Terminator--windowClosing");
}
});
這段代碼具有下列作用:定義了一個擴展於WindowAdapter類的無名類。
將windowClosing方法添加到匿名類中。
從WindowAdapter繼承6個沒有做任何事情的方法。
創建這個類的一個對象,這個對象沒有名字。
將這個對象傳遞給addWindowListener方法。
完整示例代碼如下:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
public class ListenerTest {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
AdapterFrame adapterFrame = new AdapterFrame();
WindowListener listenerListener = new TerminatorListener();
adapterFrame.addWindowListener(listenerListener);
WindowListener listenerAdapter = new TerminatorAdapter();
adapterFrame.addWindowListener(listenerAdapter);
adapterFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("Terminator--windowClosing");
}
});
adapterFrame.setVisible(true);
}
});
}
}
class AdapterFrame extends JFrame {
public AdapterFrame() {
setTitle("AdapterTest");
setSize(DEFAULT_WIDTH, DEFALUT_HEIGHT);
adapterPanel = new JPanel();
add(adapterPanel);
}
private JPanel adapterPanel;
public static final int DEFAULT_WIDTH = 300;
public static final int DEFALUT_HEIGHT = 200;
}
class TerminatorAdapter extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.out.println("TerminatorAdapter---windowClosing");
}
}
class TerminatorListener implements WindowListener {
public void windowClosing(WindowEvent e) {
System.out.println("TerminatorListener--windowClosing");
}
@Override
public void windowOpened(WindowEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowClosed(WindowEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowIconified(WindowEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowDeiconified(WindowEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowActivated(WindowEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void windowDeactivated(WindowEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
}
運行結果:
關閉AdapterTest窗口,顯示結果:
TerminatorListener--windowClosing
TerminatorAdapter---windowClosing
Terminator--windowClosing