Java圖形用戶界面設計2

二. 框架、監聽器和事件

  框架 (Frame) 是 Java 圖形用戶界面的基礎,它就是我們通常所說的窗口,是 Windows/XWindow 應用程序的典型特徵。說到 Windows/XWindow,大家很容易聯想到“事件 (Event) 驅動”。Java 的圖形用戶界面正是事件驅動的,並且由各種各樣的監聽器 (Listener) 負責捕捉各種事件。

  如果我們需要對某一個組件的某種事件進行捕捉和處理時,就需要爲其添加監聽器。比如,我們要在一個窗口 (JFrame) 激活時改變它的標題,我們就需要爲這個窗口 (JFrame 對象) 添加一個可以監聽到“激活窗口”這一事件的監聽器——WindowListener。

  怎麼添加監聽器呢?這通常由組件類提供的一個 addXXXXXListener 的方法來完成。比如 JFrame 就提供有 addWindowListener 方法添加窗口監聽器 (WindowListener)。

  一個監聽器常常不只監聽一個事件,而是可以監聽相關的多個事件。比如 WindowListener 除了監聽窗口激活事件 (windowActivate) 之外,還可以監聽窗口關閉事件 (windowClosing) 等。那麼這些事件怎麼區分呢?就靠重載監聽器類 (Class) 的多個方法 (Method) 了,監聽器監聽到某個事件後,會自動調用相關的方法。我們只要重載這個方法,就可以處理相應的事件了。

  不妨先看一個例子:

/**
* TestFrame.java
* @author Fancy
*/
import javax.swing.*;
import java.awt.event.*;

public class TestFrame extends JFrame {

 private int counter = 0;

 public TestFrame() {
  /* 使用匿名類添加一個窗口監聽器 */
  addWindowListener(new WindowAdapter() {
  public void windowClosing(WindowEvent e) {
   System.out.println("Exit when Closed event");
   System.exit(0); //退出應用程序
  }

  public void windowActivated(WindowEvent e) {
   setTitle("Test Frame " + counter++); // 改變窗口標題
  }
 });

 setResizable(false); // 設置窗口爲固定大小
 setSize(200, 150);
}

 public static void main(String[] args) {
  TestFrame tf = new TestFrame();
  tf.show();
 }

}

  這個例子中,我們設計了一個窗口類(public class TestFrame extends JFrame { ...),並且爲這個窗口添加了一個窗口監聽器 (addWindowListener(new WindowAdapter() ...)。而我們添加的這個窗口監聽器主要監聽了兩個事件:窗口關閉 (public void windowClosing(WindowEvent e) ...) 和窗口激活 (public void windowActivated(WindowEvent e) ...)。在窗口關閉事件中我們退出了整個應用程序(System.exit(0);),而在窗口激活事件中,我們改變了窗口的標題 (setTitle("Test Frame " + counter++);)。最後,我們在 main 方法中顯示了這窗口類的一個實例,運行得到下圖所示的結果:


  這個程序的運行結果就是一個什麼東西都沒有加的框架,也就是一個空窗口。那麼,你知道顯示一個窗口最主要的幾句代碼嗎?不知道沒關係,我來告訴你,顯示一個窗口只需要做三件事:生成實例(對象) -> 設置大小 -> 顯示,相應的,就是下面的三句代碼:

  JFrame frame = new JFrame("Frame's Title");
  frame.setSize(400, 300);
  frame.show();

  也許你會說:第一句的意思我清楚,第三句的意思我也明白,爲什麼一定要第二句呢?其實想想也就明白了,叫你畫一個沒法有大小的矩形你能畫出來嗎?不能。同樣,沒有大小的窗口,怎麼顯示?所以我們需要用 setSize(int width, int height) 方法爲其設置大小。我們還有另一種方法:用 JFrame 的 pack() 方法讓它自己適配一個大小。pack() 在多數時候是令人滿意的,但有時,它也會讓你哭笑不得——多試試就知道了。

  在 JFrame 中,我們使用 addWindowListener 方法加入一個監聽器 WindowListener (addWindowListener(new WindowAdapter() ...) 去監聽發生在 JFrame 上的窗口事件。WindowListener 是一個接口,在 java.awt.event 這個包中,但是上例中好象並沒有使用 WindowListener,而是使用的 WindowsAdapter 吧,這是怎麼回事?

  WindowAdapter 是 WindowsListener 接口的一個最簡單的實現,也在包 java.awt.event 中。如果我們直接使用 WindowListener 產生一個匿名類,需要實現它的每一個方法 (一共 7 個)。但 WindowAdapter 作爲 WindowListener 最簡單的實現,已經實現了它的每一個方法爲空方法 (即只包含空語句,或者說沒有語句的方法)。用 WindowAdapter 就只需要重載可能用到的方法 (上例中只有 2 個) 就行了,而不需要再去實現每一個方法。優點顯而易見——減少代碼量。

  在 JFrame 上發生的窗口事件 (WindowEvent) 包括:

  windowActivated(WindowEvent e) 窗口得到焦點時觸發
  windowClosed(WindowEvent e) 窗口關閉之後觸發
  windowClosing(WindowEvent e) 窗口關閉時觸發
  windowDeactivated(WindowEvent e) 窗口失去焦點時觸發
  windowDeiconified(WindowEvent e)
  windowIconified(WindowEvent e)
  windowOpened(WindowEvent e) 窗口打開之後觸發

  上例重載了其中兩個方法。如果在上例運行產生的窗口和另外一個應用程序窗口之間來回切換 (在 Windows 操作系統中你可以使用 Alt+Tab 進行切換)……試試看,你發現了什麼?有沒有現我們的示例窗口標題上的數字一直在增加,這便是在 windowActivated 事件中 setTitle("Test Frame " + counter++); 的功勞。

  而另一個事件處理函數 windowClosing 中的 System.exit(0) 則保證了當窗口被關閉時退出當前的 Java 應用程序。如果不作這樣的處理會怎樣呢?試驗之後你會發現,窗口雖然關閉了,但程序並沒有結束,但此時,除了使用 ^C 強行結束之外,恐怕也沒有其它辦法了。所以,這一點非常重要:如果你想在關閉窗口的時候退出應用程序,需要你自己寫代碼處理 windowClosing 事件。……也不盡然,其實還有另外一個更簡單的辦法,讓 JFrame 自己處理這件事——你只需要如下調用 JFrame 的 setDefaultCloseOperation 即可:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
  我們可以在 JFrame 對象中添加 AWT 或者 Swing 組件。但是,雖然它有 add 方法,卻不能直接用於添加組件,否則會拋出異常——不信就試試。造成這個現象的原因只有一個解釋:JFrame 不是一個容器,它只是一個框架。那麼,應該怎麼添加組件呢?

  JFrame 有一個 Content Pane,窗口是顯示的所有組件都是添加在這個 Content Pane 中。JFrame 提供了兩個方法:getContentPane 和 setContentPane 就是用於獲取和設置其 Content Pane 的。通常我們不需要重新設置 JFrame 的 Content Pane,只需要直接獲取這個 Content Pane 來添加組件等。如:(new JFrame()).getContentPane().add(new Button("test button"));
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章