Java--AWT事件處理機制

本文部分內容參考:http://bdxnote.blog.163.com/blog/static/844423520134154319780/;

1.事件處理機制:GUI程序和用戶操作的交互功能;

2.理解3個重要的概念:

事件:用戶對組件的一個操作,稱之爲一個事件;

事件源:發生事件的組件就是事件源;

事件處理器:負責處理事件的方法;

3.事件處理的步驟:

STEP1:確定事件監聽器類型之後,必須在程序中實現事件處理代碼;可以實現事件監聽器接口,可以繼承事件適配器類;
STEP2:創建事件監聽器對象;
STEP3:調用事件源的addXxxListener()方法,把事件監聽器對象註冊給事件源;

一、事件類和相應的事件監聽器接口

1.MouseEvent對應鼠標事件,包括鼠標按下、釋放、點擊等;對應的監聽器接口名MouseLister;

2.WindowEvent對應窗口事件,包括點擊了關閉按鈕,窗口得到與失去焦點,窗口被最小化等;對應的監聽器接口名WindowListener;

3.ActionEvent對應一個動作事件,代表一個具體的動作,如按鈕或菜單被鼠標單擊。對應的監聽器接口名ActionLister;

二、定義實現事件監聽器有如下幾種方法:
方法1:使用內部匿名類作爲事件監聽器;這種方法適用於簡單的事件處理器對象;如下:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyGuiClass extends JFrame
{
  public MyGuiClass()
  {
    ......
    component = new Component();
    component.addXxxListener
    (
      new XxxListener() //內部匿名類
      {
        public void 事件處理函數(XxxEvent e)
        {
          //事件處理代碼;
        }
      }
    );
    ......
  }
}
其中,new XxxListener()就是一個匿名內部類;其實就是在實現類的同時使用new運算符構造一個該類的對象,並把它作爲addXxxListener()的參數;即:把內部匿名類的定義寫到組件的事件處理器註冊函數的參數列表的位置;
方法2:使用內部命名類作爲事件監聽器;就是在GUI程序類體內部實現事件監聽器類;如下:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyGuiClass extends JFrame
{
  public MyGuiClass()
  {
    ......
    component = new Component();
    component.addXxxListener(new InnerClass());
    ......
  }
  /************內部命名類的定義************/
  class InnerClass implements XxxListener //或extends XxxAdapter;
  {
    public void 事件處理函數(XxxEvent e)
    {
      //事件處理代碼;
    }
  }
}
方法3:使用外部命名類作爲事件監聽器;就是在GUI程序類體外部實現事件監聽器類;如下:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyGuiClass extends JFrame
{
  public MyGuiClass()
  {
    ......
    component = new Component();
    component.addXxxListener(new OuterClass());
    ......
  }
}
/************外部命名類的定義************/
class OuterClass implements XxxListener //或extends XxxAdapter;
{
  public void 事件處理函數(XxxEvent e)
  {
    //事件處理代碼;
  }
  ......
}
方法4:使用當前提供GUI界面的類自身作爲監聽器;就是把提供應用程序GUI界面的類自身當做監聽器類;如下:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyGuiClass extends JFrame implements XxxListener //或extends XxxAdapter;
{
  public MyGuiClass()
  {
    ......
    component = new Component();
    component.addXxxListener(this);
    ......
  }
  public void 事件處理函數(XxxEvent e)
  {
    //事件處理代碼;
  }
  ......
}
備註:
(1)使用匿名內部類存在很多問題;首先,根據組件在代碼中被定義的位置不同,類的定義以及處理事件的代碼將分散在程序的各個部分,而不是集中在一起的,不方便維護;各個事件的處理全部由嵌套的程序塊組成,視覺上很難定位程序代碼;如果事件處理程序比較複雜,內部類中的代碼將變得很長,這就很難找到相應的組件定義的位置;內部匿名類的代碼也不能被複用;
(2)使用一般的命名內部類可以解決匿名內部類的全部問題;但是,一般的命名內部類也有一些問題,它可以訪問當前提供GUI界面的類的全部成員,這破壞了類的封裝性,會造成數據的不安全訪問;
(3)使用外部命名類可以避免其它三種方式的問題;但是又有新的問題了,外部命名類不能很方便地訪問當前提供GUI界面的類的成員;
(4)使用當前提供GUI界面的類自身作爲監聽器,這種方式看上去比較完美了;但是這種方式只能實現事件監聽器接口,實現接口的全部事件處理函數,即便事件處理函數是空函數,也要寫出來;而不能繼承事件適配器類;因爲它已經繼承了Java的界面類JFrame;
綜合比較,使用一般的內部命名類還是比較方便的;
三、事件適配器:
很多事件監聽器接口中都定義了很多抽象方法,而往往只用到其中的一個或很少的幾個;根據Java的語法規則,實現接口時,必須要把其中定義的全部方法都實現,對那些不需要的方法,填寫成空語句即可;
例如:窗口監聽器接口WindowListener有7個方法,而很多時候,程序可能只用到其中的windowClosing()方法,以便實現窗口右上角的關閉按鈕的關閉代碼;但是其它6個方法也必須實現,即便是空方法;這樣就使得程序編寫顯得非常麻煩;
爲了解決這個問題,事件適配器類就出現了;爲了簡化程序,Java中預定義了一些特殊類,這些類已經實現了相應的接口,所有方法都已經寫上了空語句;使得在編寫事件監聽器類時,便可以通過繼承這些特殊的類來達到實現相應的事件監聽器接口的目的;同時又可以只選擇程序中需要的方法進行重寫,非常方便;
Java中把這些預定義的類稱爲事件適配器類,類似於監聽器接口;爲了方便使用,適配器類的名稱有一定的規則:只需要把相應接口名稱中的Listener改爲Adapter即可;例如,窗口監聽器接口WindowListener對應的適配器類是WindowAdapter;鼠標監聽器接口MouseListener對應的適配器類是MouseAdapter;還有一些事件監聽器接口,本身就只有一個事件處理函數,所以就不需要有對應的適配器類;比如,ActionListener接口,它就只有一個事件處理函數,JDK中就沒有定義該接口的適配器類;
由於Java不支持多繼承,所以,事件監聽器實現方法4"使用當前提供GUI界面的類自身作爲監聽器"就不能使用事件適配器類,因爲它已經繼承了Java的GUI類;
通常把GUI界面類與事件處理器類分離在兩個類中,這樣有利於界面和業務邏輯的分離,提高了代碼的靈活性和可重用性;然而把事件處理器類與GUI界面類分開放在兩個類中時,又使得兩個類之間的數據交流變得比較複雜;因此,綜合評定各種優缺點,經常的做法就是把事件處理器類定義成GUI界面類的內部命名類,以便於從事件處理器中能夠直接訪問GUI界面類中的成員;
備註:同一個組件上可以註冊多個事件監聽器,同一個事件監聽器也可以註冊到多個組件上,同一個事件監聽器也可以在同一個組件上添加和刪除多次;這些特點都得益於Observer設計模式;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章