Java事件處理與發送

任何時候,按下鍵盤或鼠標的鍵就產生了事件。組件接受和處理事件的方式自JDK1.1以來都保持不變。Swing組件能夠產生許多不同類別的事件,包括那些在java.awt.event包以及在javax.swing.event包中的事件。Swing新引入的那些事件類別往往是與特定Swing組件相關的。每一個事件類別都是一個對象,它至少指明瞭事件的發生源,往往還帶有其它消息,如該事件的類別、在事件發生前和發生後事件源狀態的變化,等等。事件源大部分是普通的組件或模型(models, MVC中的M,在以後的blog中可能會介紹Swing組件的MVC結構)。其它的對象也可能產生事件。

 

要想收到事件產生的通知,我們需要在目標對象上註冊事件監聽器。事件監聽器是任意XXListener類或接口的具體實現(XX代指事件的類型)。XXListener是定義在java.awt.eventjava.beansjavax.swing.event包中的類或接口。在每個接口中至少定義了一個方法(method),該方法以對應的XXEvent作爲參數。支持發送XXEvent事件發生通知的類都須實現XXListener接口,同時提供相應的addXXListener()removeXXListener()方法來註冊和移除這些事件監聽器,大部分的事件目標對象(target)都允許註冊任意多個事件監聽器。通常支持XXEvent的類都提供受保護的方法(protected methodfireXX()來構造事件對象及將它送至事件處理器(event handler)進行處理。

javax.swing.event.EventListenerList

EventListenerList是一個包含XXEvent/XXListener對(pairs)的陣列(數組)。JComponent及其派生類使用一個EventListenerList對象來維護其事件監聽器。所有默認的模型(models)同樣維護事件監聽器和一個EventListenerList。當一個監聽器被註冊到一個Swing組件或模型(model)時,對應的事件的Class實例(用來標識事件類別)被添加至EventListenerList陣列,後面緊隨該監聽器本身(即一個XXEvent/XXListener對)。因爲這些對是儲存在陣列而不是在可變的集合(mutable collection)中(出於對效率的考慮),每一次添加和移除都會調用System.arrayCopy()來生成一個新的陣列。當收到事件時,陣列被遍歷,事件就會被送至擁有其類型的每一個事件監聽器。由於陣列是按XXEvent, XXListener, YYEvent, YYListener, ... 的方式排列的,某個事件類別的監聽器總是緊隨其後。這種方式使得事件處理十分高效。爲了線程安全,當從EventListenerList添加和移除監聽器時,方法訪問陣列必須同步。

JComponent定義了一個名爲listenerList的受保護EventListListener屬性,因而所有它的子類都繼承了這個屬性。Swing組件直接透過listenerList屬性來管理其大部分事件監聽器。

事件發送線程

事件監聽器在事件發送線程(一個java.awt.EventDispatchThread類的實例)中接受並處理事件。所有的繪製和組件佈局也被要求在此線程中發生。事件發送線程在AWTSwing中具有頭等的重要性,在應用中控制組件狀態和顯示的隨時更新方面扮演着關鍵的角色。

與此線程相關的是一個事件的FIFOFirst In First Out,先進先出)隊列:系統事件隊列(java.awt.EventQueue的一個實例)。跟所有的FIFO隊列一樣,系統事件隊列也是被線性填充的。無論是更新組件屬性,佈局,或是重新繪製,每一個請求依次運行事件處理代碼。所有事件被依次處理是爲了避免像某個組件的狀態在它重新繪製的中途被意外改變這樣的情況。知道這一點後,我們就要避免在事件發送線程之外去發送事件。比如說,在另一個線程中直接調用fireXX()方法就是不安全的。我們同時也必須保證事件處理代碼和繪製代碼儘快地執行完,否則整個系統隊列就會被阻塞,被迫等待某個事件被處理,重新繪製,或是佈局完畢,而我們的應用程序則像是被“凍結”或是失去響應。
==============================================================================================
// Thanks to Matthew Robinson and Pavel Vorobiev, Ph.D for their great book Swing, this article is translated form
// this book, 1st edition. You can find these text in their book (in English) of Chapter 2.
=================================================================================

 

要想收到事件產生的通知,我們需要在目標對象上註冊事件監聽器。事件監聽器是任意XXListener類或接口的具體實現(XX代指事件的類型)。XXListener是定義在java.awt.eventjava.beansjavax.swing.event包中的類或接口。在每個接口中至少定義了一個方法(method),該方法以對應的XXEvent作爲參數。支持發送XXEvent事件發生通知的類都須實現XXListener接口,同時提供相應的addXXListener()removeXXListener()方法來註冊和移除這些事件監聽器,大部分的事件目標對象(target)都允許註冊任意多個事件監聽器。通常支持XXEvent的類都提供受保護的方法(protected methodfireXX()來構造事件對象及將它送至事件處理器(event handler)進行處理。

javax.swing.event.EventListenerList

EventListenerList是一個包含XXEvent/XXListener對(pairs)的陣列(數組)。JComponent及其派生類使用一個EventListenerList對象來維護其事件監聽器。所有默認的模型(models)同樣維護事件監聽器和一個EventListenerList。當一個監聽器被註冊到一個Swing組件或模型(model)時,對應的事件的Class實例(用來標識事件類別)被添加至EventListenerList陣列,後面緊隨該監聽器本身(即一個XXEvent/XXListener對)。因爲這些對是儲存在陣列而不是在可變的集合(mutable collection)中(出於對效率的考慮),每一次添加和移除都會調用System.arrayCopy()來生成一個新的陣列。當收到事件時,陣列被遍歷,事件就會被送至擁有其類型的每一個事件監聽器。由於陣列是按XXEvent, XXListener, YYEvent, YYListener, ... 的方式排列的,某個事件類別的監聽器總是緊隨其後。這種方式使得事件處理十分高效。爲了線程安全,當從EventListenerList添加和移除監聽器時,方法訪問陣列必須同步。

JComponent定義了一個名爲listenerList的受保護EventListListener屬性,因而所有它的子類都繼承了這個屬性。Swing組件直接透過listenerList屬性來管理其大部分事件監聽器。

事件發送線程

事件監聽器在事件發送線程(一個java.awt.EventDispatchThread類的實例)中接受並處理事件。所有的繪製和組件佈局也被要求在此線程中發生。事件發送線程在AWTSwing中具有頭等的重要性,在應用中控制組件狀態和顯示的隨時更新方面扮演着關鍵的角色。

與此線程相關的是一個事件的FIFOFirst In First Out,先進先出)隊列:系統事件隊列(java.awt.EventQueue的一個實例)。跟所有的FIFO隊列一樣,系統事件隊列也是被線性填充的。無論是更新組件屬性,佈局,或是重新繪製,每一個請求依次運行事件處理代碼。所有事件被依次處理是爲了避免像某個組件的狀態在它重新繪製的中途被意外改變這樣的情況。知道這一點後,我們就要避免在事件發送線程之外去發送事件。比如說,在另一個線程中直接調用fireXX()方法就是不安全的。我們同時也必須保證事件處理代碼和繪製代碼儘快地執行完,否則整個系統隊列就會被阻塞,被迫等待某個事件被處理,重新繪製,或是佈局完畢,而我們的應用程序則像是被“凍結”或是失去響應。
==============================================================================================
// Thanks to Matthew Robinson and Pavel Vorobiev, Ph.D for their great book Swing, this article is translated form
// this book, 1st edition. You can find these text in their book (in English) of Chapter 2.
=================================================================================

JDK1.1以來都保持不變。Swing組件能夠產生許多不同類別的事件,包括那些在java.awt.event包以及在javax.swing.event包中的事件。Swing新引入的那些事件類別往往是與特定Swing組件相關的。每一個事件類別都是一個對象,它至少指明瞭事件的發生源,往往還帶有其它消息,如該事件的類別、在事件發生前和發生後事件源狀態的變化,等等。事件源大部分是普通的組件或模型(models, MVC中的M,在以後的blog中可能會介紹Swing組件的MVC結構)。其它的對象也可能產生事件。

 

要想收到事件產生的通知,我們需要在目標對象上註冊事件監聽器。事件監聽器是任意XXListener類或接口的具體實現(XX代指事件的類型)。XXListener是定義在java.awt.eventjava.beansjavax.swing.event包中的類或接口。在每個接口中至少定義了一個方法(method),該方法以對應的XXEvent作爲參數。支持發送XXEvent事件發生通知的類都須實現XXListener接口,同時提供相應的addXXListener()removeXXListener()方法來註冊和移除這些事件監聽器,大部分的事件目標對象(target)都允許註冊任意多個事件監聽器。通常支持XXEvent的類都提供受保護的方法(protected methodfireXX()來構造事件對象及將它送至事件處理器(event handler)進行處理。

javax.swing.event.EventListenerList

EventListenerList是一個包含XXEvent/XXListener對(pairs)的陣列(數組)。JComponent及其派生類使用一個EventListenerList對象來維護其事件監聽器。所有默認的模型(models)同樣維護事件監聽器和一個EventListenerList。當一個監聽器被註冊到一個Swing組件或模型(model)時,對應的事件的Class實例(用來標識事件類別)被添加至EventListenerList陣列,後面緊隨該監聽器本身(即一個XXEvent/XXListener對)。因爲這些對是儲存在陣列而不是在可變的集合(mutable collection)中(出於對效率的考慮),每一次添加和移除都會調用System.arrayCopy()來生成一個新的陣列。當收到事件時,陣列被遍歷,事件就會被送至擁有其類型的每一個事件監聽器。由於陣列是按XXEvent, XXListener, YYEvent, YYListener, ... 的方式排列的,某個事件類別的監聽器總是緊隨其後。這種方式使得事件處理十分高效。爲了線程安全,當從EventListenerList添加和移除監聽器時,方法訪問陣列必須同步。

JComponent定義了一個名爲listenerList的受保護EventListListener屬性,因而所有它的子類都繼承了這個屬性。Swing組件直接透過listenerList屬性來管理其大部分事件監聽器。

事件發送線程

事件監聽器在事件發送線程(一個java.awt.EventDispatchThread類的實例)中接受並處理事件。所有的繪製和組件佈局也被要求在此線程中發生。事件發送線程在AWTSwing中具有頭等的重要性,在應用中控制組件狀態和顯示的隨時更新方面扮演着關鍵的角色。

與此線程相關的是一個事件的FIFOFirst In First Out,先進先出)隊列:系統事件隊列(java.awt.EventQueue的一個實例)。跟所有的FIFO隊列一樣,系統事件隊列也是被線性填充的。無論是更新組件屬性,佈局,或是重新繪製,每一個請求依次運行事件處理代碼。所有事件被依次處理是爲了避免像某個組件的狀態在它重新繪製的中途被意外改變這樣的情況。知道這一點後,我們就要避免在事件發送線程之外去發送事件。比如說,在另一個線程中直接調用fireXX()方法就是不安全的。我們同時也必須保證事件處理代碼和繪製代碼儘快地執行完,否則整個系統隊列就會被阻塞,被迫等待某個事件被處理,重新繪製,或是佈局完畢,而我們的應用程序則像是被“凍結”或是失去響應。
==============================================================================================
// Thanks to Matthew Robinson and Pavel Vorobiev, Ph.D for their great book Swing, this article is translated form
// this book, 1st edition. You can find these text in their book (in English) in Chapter 2.
=================================================================================

 

要想收到事件產生的通知,我們需要在目標對象上註冊事件監聽器。事件監聽器是任意XXListener類或接口的具體實現(XX代指事件的類型)。XXListener是定義在java.awt.eventjava.beansjavax.swing.event包中的類或接口。在每個接口中至少定義了一個方法(method),該方法以對應的XXEvent作爲參數。支持發送XXEvent事件發生通知的類都須實現XXListener接口,同時提供相應的addXXListener()removeXXListener()方法來註冊和移除這些事件監聽器,大部分的事件目標對象(target)都允許註冊任意多個事件監聽器。通常支持XXEvent的類都提供受保護的方法(protected methodfireXX()來構造事件對象及將它送至事件處理器(event handler)進行處理。

javax.swing.event.EventListenerList

EventListenerList是一個包含XXEvent/XXListener對(pairs)的陣列(數組)。JComponent及其派生類使用一個EventListenerList對象來維護其事件監聽器。所有默認的模型(models)同樣維護事件監聽器和一個EventListenerList。當一個監聽器被註冊到一個Swing組件或模型(model)時,對應的事件的Class實例(用來標識事件類別)被添加至EventListenerList陣列,後面緊隨該監聽器本身(即一個XXEvent/XXListener對)。因爲這些對是儲存在陣列而不是在可變的集合(mutable collection)中(出於對效率的考慮),每一次添加和移除都會調用System.arrayCopy()來生成一個新的陣列。當收到事件時,陣列被遍歷,事件就會被送至擁有其類型的每一個事件監聽器。由於陣列是按XXEvent, XXListener, YYEvent, YYListener, ... 的方式排列的,某個事件類別的監聽器總是緊隨其後。這種方式使得事件處理十分高效。爲了線程安全,當從EventListenerList添加和移除監聽器時,方法訪問陣列必須同步。

JComponent定義了一個名爲listenerList的受保護EventListListener屬性,因而所有它的子類都繼承了這個屬性。Swing組件直接透過listenerList屬性來管理其大部分事件監聽器。

事件發送線程

事件監聽器在事件發送線程(一個java.awt.EventDispatchThread類的實例)中接受並處理事件。所有的繪製和組件佈局也被要求在此線程中發生。事件發送線程在AWTSwing中具有頭等的重要性,在應用中控制組件狀態和顯示的隨時更新方面扮演着關鍵的角色。

與此線程相關的是一個事件的FIFOFirst In First Out,先進先出)隊列:系統事件隊列(java.awt.EventQueue的一個實例)。跟所有的FIFO隊列一樣,系統事件隊列也是被線性填充的。無論是更新組件屬性,佈局,或是重新繪製,每一個請求依次運行事件處理代碼。所有事件被依次處理是爲了避免像某個組件的狀態在它重新繪製的中途被意外改變這樣的情況。知道這一點後,我們就要避免在事件發送線程之外去發送事件。比如說,在另一個線程中直接調用fireXX()方法就是不安全的。我們同時也必須保證事件處理代碼和繪製代碼儘快地執行完,否則整個系統隊列就會被阻塞,被迫等待某個事件被處理,重新繪製,或是佈局完畢,而我們的應用程序則像是被“凍結”或是失去響應。
==============================================================================================
// Thanks to Matthew Robinson and Pavel Vorobiev, Ph.D for their great book Swing, this article is translated form
// this book, 1st edition. You can find these text in their book (in English) of Chapter 2.
=================================================================================

發佈了0 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章