Java WindowAdapter適配器類

  並不是所有的事件處理都像按鈕點擊那樣簡單。在正規的程序中,往往希望用戶在確認沒有丟失所做工作之後再關閉程序。當用戶關閉框架時,可能希望彈出一個對話框來警告用戶沒有保存的工作有可能會丟失,只有在用戶確認之後才退出程序。

  當程序用戶試圖關閉一個框架窗口時,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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章