5.2 AWT事件處理模型
上一節(jié)中的主要內(nèi)容是如何放置各種組件,使圖形界面更加豐富多彩,但是還不能響應(yīng)用戶的任何操作,要能夠讓圖形界面接收用戶的操作,就必須給各個(gè)組件加上事件處理機(jī)制。在事件處理的過程中,主要涉及三類對(duì)象:
Event-事件,用戶對(duì)界面操作在java語言上的描述,以類的形式出現(xiàn),例如鍵盤操作對(duì)應(yīng)的事件類是KeyEvent。
Event Source-事件源,事件發(fā)生的場(chǎng)所,通常就是各個(gè)組件,例如按鈕Button。
Event handler-事件處理者,接收事件對(duì)象并對(duì)其進(jìn)行處理的對(duì)象
例如,如果用戶用鼠標(biāo)單擊了按鈕對(duì)象button,則該按鈕button就是事件源,而java運(yùn)行時(shí)系統(tǒng)會(huì)生成ActionEvent類的對(duì)象actionE,該對(duì)象中描述了該單擊事件發(fā)生時(shí)的一些信息,然后,事件處理者對(duì)象將接收由java運(yùn)行時(shí)系統(tǒng)傳遞過來的事件對(duì)象actionE并進(jìn)行相應(yīng)的處理。
由于同一個(gè)事件源上可能發(fā)生多種事件,因此java采取了授權(quán)處理機(jī)制(Delegation Model),事件源可以把在其自身所有可能發(fā)生的事件分別授權(quán)給不同的事件處理者來處理。比如在Canvas對(duì)象上既可能發(fā)生鼠標(biāo)事件,也可能發(fā)生鍵盤事件,該Canvas對(duì)象就可以授權(quán)給事件處理者一來處理鼠標(biāo)事件,同時(shí)授權(quán)給事件處理者二來處理鍵盤事件。有時(shí)也將事件處理者稱為監(jiān)聽器,主要原因也在于監(jiān)聽器時(shí)刻監(jiān)聽著事件源上所有發(fā)生的事件類型,一旦該事件類型與自己所負(fù)責(zé)處理的事件類型一致,就馬上進(jìn)行處理。授權(quán)模型把事件的處理委托給外部的處理實(shí)體進(jìn)行處理,實(shí)現(xiàn)了將事件源和監(jiān)聽器分開的機(jī)制。事件處理者(監(jiān)聽器)通常是一個(gè)類,該類如果要能夠處理某種類型的事件,就必須實(shí)現(xiàn)與該事件類型相對(duì)的接口。例如例5.9中類ButtonHandler之所以能夠處理ActionEvent事件,原因在于它實(shí)現(xiàn)了與ActionEvent事件對(duì)應(yīng)的接口ActionListener。每個(gè)事件類都有一個(gè)與之相對(duì)應(yīng)的接口。 來源:www.examda.com
將事件源對(duì)象和事件處理器(事件監(jiān)聽器)分開。如圖5.2所示
打個(gè)不太恰當(dāng)?shù)谋扔?,比如說有一位李先生,李先生可能會(huì)發(fā)生很多法律糾紛,可能是民事法律糾紛,也可能是刑事法律糾紛,那么李先生可以請(qǐng)律師,他可以授權(quán)王律師負(fù)責(zé)幫他打民事法律的官司,同時(shí)也可以授權(quán)張律師幫他打刑事法律的官司。這個(gè)請(qǐng)律師的過程從李先生的角度來看,就是授權(quán)的過程,而從王律師和張律師的角度來看,一旦被授權(quán),他們就得時(shí)刻對(duì)李先生負(fù)責(zé),"監(jiān)聽"著李先生,一旦發(fā)生民事糾紛了,王律師就要馬上去處理,而一旦發(fā)生刑事糾紛了,張律師就要馬上進(jìn)行處理。此時(shí)此刻,李先生就是事件源,王律師是一個(gè)事件處理者,張律師是另外一個(gè)事件處理者,民事糾紛和刑事糾紛就是不同類型的事件。
使用授權(quán)處理模型進(jìn)行事件處理的一般方法歸納如下:
1.對(duì)于某種類型的事件XXXEvent, 要想接收并處理這類事件,必須定義相應(yīng)的事件監(jiān)聽器類,該類需要實(shí)現(xiàn)與該事件相對(duì)應(yīng)的接口XXXListener;
2.事件源實(shí)例化以后,必須進(jìn)行授權(quán),注冊(cè)該類事件的監(jiān)聽器,使用addXXXListener(XXXListener ) 方法來注冊(cè)監(jiān)聽器。
5.2.1 事件類
與AWT有關(guān)的所有事件類都由java.awt.AWTEvent類派生,它也是EventObject類的子類。AWT事件共有10類,可以歸為兩大類:低級(jí)事件和高級(jí)事件。
java.util.EventObject類是所有事件對(duì)象的基礎(chǔ)父類,所有事件都是由它派生出來的。AWT的相關(guān)事件繼承于java.awt.AWTEvent類,這些AWT事件分為兩大類:低級(jí)事件和高級(jí)事件,低級(jí)事件是指基于組件和容器的事件,當(dāng)一個(gè)組件上發(fā)生事件,如:鼠標(biāo)的進(jìn)入,點(diǎn)擊,拖放等,或組件的窗口開關(guān)等,觸發(fā)了組件事件。高級(jí)事件是基于語義的事件,它可以不和特定的動(dòng)作相關(guān)聯(lián),而依賴于觸發(fā)此事件的類,如在TextField中按Enter鍵會(huì)觸發(fā)ActionEvent事件,滑動(dòng)滾動(dòng)條會(huì)觸發(fā)AdjustmentEvent事件,或是選中項(xiàng)目列表的某一條就會(huì)觸發(fā)ItemEvent事件。
低級(jí)事件
ComponentEvent( 組件事件:組件尺寸的變化,移動(dòng))
ContainerEvent( 容器事件:組件增加,移動(dòng))
WindowEvent( 窗口事件:關(guān)閉窗口,窗口閉合,圖標(biāo)化)
FocusEvent( 焦點(diǎn)事件:焦點(diǎn)的獲得和丟失)
KeyEvent( 鍵盤事件:鍵按下、釋放)
MouseEvent( 鼠標(biāo)事件:鼠標(biāo)單擊,移動(dòng))
高級(jí)事件(語義事件)
ActionEvent(動(dòng)作事件:按鈕按下,TextField中按Enter鍵)
AdjustmentEvent(調(diào)節(jié)事件:在滾動(dòng)條上移動(dòng)滑塊以調(diào)節(jié)數(shù)值)
ItemEvent(項(xiàng)目事件:選擇項(xiàng)目,不選擇"項(xiàng)目改變")
TextEvent(文本事件,文本對(duì)象改變)
5.2.2 事件監(jiān)聽器
每類事件都有對(duì)應(yīng)的事件監(jiān)聽器,監(jiān)聽器是接口,根據(jù)動(dòng)作來定義方法。
例如,與鍵盤事件KeyEvent相對(duì)應(yīng)的接口是:
public interface KeyListener extends EventListener {
public void keyPressed(KeyEvent ev);
public void keyReleased(KeyEvent ev);
public void keyTyped(KeyEvent ev);
}
注意到在本接口中有三個(gè)方法,那么java運(yùn)行時(shí)系統(tǒng)何時(shí)調(diào)用哪個(gè)方法?其實(shí)根據(jù)這三個(gè)方法的方法名就能夠知道應(yīng)該是什么時(shí)候調(diào)用哪個(gè)方法執(zhí)行了。當(dāng)鍵盤剛按下去時(shí),將調(diào)用keyPressed( )方法執(zhí)行,當(dāng)鍵盤抬起來時(shí),將調(diào)用keyReleased( )方法執(zhí)行,當(dāng)鍵盤敲擊一次時(shí),將調(diào)用keyTyped( )方法執(zhí)行。
上一節(jié)中的主要內(nèi)容是如何放置各種組件,使圖形界面更加豐富多彩,但是還不能響應(yīng)用戶的任何操作,要能夠讓圖形界面接收用戶的操作,就必須給各個(gè)組件加上事件處理機(jī)制。在事件處理的過程中,主要涉及三類對(duì)象:
Event-事件,用戶對(duì)界面操作在java語言上的描述,以類的形式出現(xiàn),例如鍵盤操作對(duì)應(yīng)的事件類是KeyEvent。
Event Source-事件源,事件發(fā)生的場(chǎng)所,通常就是各個(gè)組件,例如按鈕Button。
Event handler-事件處理者,接收事件對(duì)象并對(duì)其進(jìn)行處理的對(duì)象
例如,如果用戶用鼠標(biāo)單擊了按鈕對(duì)象button,則該按鈕button就是事件源,而java運(yùn)行時(shí)系統(tǒng)會(huì)生成ActionEvent類的對(duì)象actionE,該對(duì)象中描述了該單擊事件發(fā)生時(shí)的一些信息,然后,事件處理者對(duì)象將接收由java運(yùn)行時(shí)系統(tǒng)傳遞過來的事件對(duì)象actionE并進(jìn)行相應(yīng)的處理。
由于同一個(gè)事件源上可能發(fā)生多種事件,因此java采取了授權(quán)處理機(jī)制(Delegation Model),事件源可以把在其自身所有可能發(fā)生的事件分別授權(quán)給不同的事件處理者來處理。比如在Canvas對(duì)象上既可能發(fā)生鼠標(biāo)事件,也可能發(fā)生鍵盤事件,該Canvas對(duì)象就可以授權(quán)給事件處理者一來處理鼠標(biāo)事件,同時(shí)授權(quán)給事件處理者二來處理鍵盤事件。有時(shí)也將事件處理者稱為監(jiān)聽器,主要原因也在于監(jiān)聽器時(shí)刻監(jiān)聽著事件源上所有發(fā)生的事件類型,一旦該事件類型與自己所負(fù)責(zé)處理的事件類型一致,就馬上進(jìn)行處理。授權(quán)模型把事件的處理委托給外部的處理實(shí)體進(jìn)行處理,實(shí)現(xiàn)了將事件源和監(jiān)聽器分開的機(jī)制。事件處理者(監(jiān)聽器)通常是一個(gè)類,該類如果要能夠處理某種類型的事件,就必須實(shí)現(xiàn)與該事件類型相對(duì)的接口。例如例5.9中類ButtonHandler之所以能夠處理ActionEvent事件,原因在于它實(shí)現(xiàn)了與ActionEvent事件對(duì)應(yīng)的接口ActionListener。每個(gè)事件類都有一個(gè)與之相對(duì)應(yīng)的接口。 來源:www.examda.com
將事件源對(duì)象和事件處理器(事件監(jiān)聽器)分開。如圖5.2所示
打個(gè)不太恰當(dāng)?shù)谋扔?,比如說有一位李先生,李先生可能會(huì)發(fā)生很多法律糾紛,可能是民事法律糾紛,也可能是刑事法律糾紛,那么李先生可以請(qǐng)律師,他可以授權(quán)王律師負(fù)責(zé)幫他打民事法律的官司,同時(shí)也可以授權(quán)張律師幫他打刑事法律的官司。這個(gè)請(qǐng)律師的過程從李先生的角度來看,就是授權(quán)的過程,而從王律師和張律師的角度來看,一旦被授權(quán),他們就得時(shí)刻對(duì)李先生負(fù)責(zé),"監(jiān)聽"著李先生,一旦發(fā)生民事糾紛了,王律師就要馬上去處理,而一旦發(fā)生刑事糾紛了,張律師就要馬上進(jìn)行處理。此時(shí)此刻,李先生就是事件源,王律師是一個(gè)事件處理者,張律師是另外一個(gè)事件處理者,民事糾紛和刑事糾紛就是不同類型的事件。
使用授權(quán)處理模型進(jìn)行事件處理的一般方法歸納如下:
1.對(duì)于某種類型的事件XXXEvent, 要想接收并處理這類事件,必須定義相應(yīng)的事件監(jiān)聽器類,該類需要實(shí)現(xiàn)與該事件相對(duì)應(yīng)的接口XXXListener;
2.事件源實(shí)例化以后,必須進(jìn)行授權(quán),注冊(cè)該類事件的監(jiān)聽器,使用addXXXListener(XXXListener ) 方法來注冊(cè)監(jiān)聽器。
5.2.1 事件類
與AWT有關(guān)的所有事件類都由java.awt.AWTEvent類派生,它也是EventObject類的子類。AWT事件共有10類,可以歸為兩大類:低級(jí)事件和高級(jí)事件。
java.util.EventObject類是所有事件對(duì)象的基礎(chǔ)父類,所有事件都是由它派生出來的。AWT的相關(guān)事件繼承于java.awt.AWTEvent類,這些AWT事件分為兩大類:低級(jí)事件和高級(jí)事件,低級(jí)事件是指基于組件和容器的事件,當(dāng)一個(gè)組件上發(fā)生事件,如:鼠標(biāo)的進(jìn)入,點(diǎn)擊,拖放等,或組件的窗口開關(guān)等,觸發(fā)了組件事件。高級(jí)事件是基于語義的事件,它可以不和特定的動(dòng)作相關(guān)聯(lián),而依賴于觸發(fā)此事件的類,如在TextField中按Enter鍵會(huì)觸發(fā)ActionEvent事件,滑動(dòng)滾動(dòng)條會(huì)觸發(fā)AdjustmentEvent事件,或是選中項(xiàng)目列表的某一條就會(huì)觸發(fā)ItemEvent事件。
低級(jí)事件
ComponentEvent( 組件事件:組件尺寸的變化,移動(dòng))
ContainerEvent( 容器事件:組件增加,移動(dòng))
WindowEvent( 窗口事件:關(guān)閉窗口,窗口閉合,圖標(biāo)化)
FocusEvent( 焦點(diǎn)事件:焦點(diǎn)的獲得和丟失)
KeyEvent( 鍵盤事件:鍵按下、釋放)
MouseEvent( 鼠標(biāo)事件:鼠標(biāo)單擊,移動(dòng))
高級(jí)事件(語義事件)
ActionEvent(動(dòng)作事件:按鈕按下,TextField中按Enter鍵)
AdjustmentEvent(調(diào)節(jié)事件:在滾動(dòng)條上移動(dòng)滑塊以調(diào)節(jié)數(shù)值)
ItemEvent(項(xiàng)目事件:選擇項(xiàng)目,不選擇"項(xiàng)目改變")
TextEvent(文本事件,文本對(duì)象改變)
5.2.2 事件監(jiān)聽器
每類事件都有對(duì)應(yīng)的事件監(jiān)聽器,監(jiān)聽器是接口,根據(jù)動(dòng)作來定義方法。
例如,與鍵盤事件KeyEvent相對(duì)應(yīng)的接口是:
public interface KeyListener extends EventListener {
public void keyPressed(KeyEvent ev);
public void keyReleased(KeyEvent ev);
public void keyTyped(KeyEvent ev);
}
注意到在本接口中有三個(gè)方法,那么java運(yùn)行時(shí)系統(tǒng)何時(shí)調(diào)用哪個(gè)方法?其實(shí)根據(jù)這三個(gè)方法的方法名就能夠知道應(yīng)該是什么時(shí)候調(diào)用哪個(gè)方法執(zhí)行了。當(dāng)鍵盤剛按下去時(shí),將調(diào)用keyPressed( )方法執(zhí)行,當(dāng)鍵盤抬起來時(shí),將調(diào)用keyReleased( )方法執(zhí)行,當(dāng)鍵盤敲擊一次時(shí),將調(diào)用keyTyped( )方法執(zhí)行。