13、Java Swing事件监听:事件处理模型和事件监听器
事件表示程序和用戶之間的交互,例如在文本框中輸入,在列表框或組合框中選擇,選中復選框和單選框,單擊按鈕等。事件處理表示程序對事件的響應,對用戶的交互或者說對事件的處理是事件處理程序完成的。
當事件發生時,系統會自動捕捉這一事件,創建表示動作的事件對象并把它們分派給程序內的事件處理程序代碼。這種代碼確定了如何處理此事件以使用戶得到相應的回答。
事件處理模型
前面我們講解了如何放置各種組件,使圖形界面更加豐富多彩,但是還不能響應用戶的任何操作。若使圖形界面能夠接收用戶的操作,必須給各個組件加上事件處理機制。在事件處理的過程中,主要涉及三類對象。
- Event(事件):用戶對組件的一次操作稱為一個事件,以類的形式出現。例如,鍵盤操作對應的事件類是 KeyEvent。
- Event Source(事件源):事件發生的場所,通常就是各個組件,例如按鈕 Button。
- Event Handler(事件處理者):接收事件對象并對其進行處理的對象事件處理器,通常就是某個 Java 類中負責處理事件的成員方法。
例如,如果鼠標單擊了按鈕對象 Button,則該按鈕 Button 就是事件源,而 Java 運行時系統會生成 ActionEvent 類的對象 ActionEvent,該對象中描述了單擊事件發生時的一些信息。之后,事件處理者對象將接收由 Java 運行時系統傳遞過來的事件對象 ActionEvent,并進行相應的處理。事件處理模型如圖 1 所示。
由于同一個事件源上可能發生多種事件,因此,Java 采取了授權模型(Delegation Model),事件源可以把在其自身上所有可能發生的事件分別授權給不同的事件處理者來處理。例如,在 Panel 對象上既可能發生鼠標事件,也可能發生鍵盤事件,該 Panel 對象可以授權給事件處理者 a 來處理鼠標事件,同時授權給事件處理者 b 來處理鍵盤事件。
有時也將事件處理者稱為監聽器,主要原因在于監聽器時刻監聽事件源上所有發生的事件類型,一旦該事件類型與自己所負責處理的事件類型一致,就馬上進行處理。授權模型把事件的處理委托給外部的處理實體進行處理,實現了將事件源和監聽器分開的機制。
事件處理者(監聽器)通常是一個類,該類如果能夠處理某種類型的事件,就必須實現與該事件類型相對的接口。例如,一個 ButtonHandler 類之所以能夠處理 ActionEvent 事件,原因在于它實現了與 ActionEvent 事件對應的接口 ActionListener。每個事件類都有一個與之相對應的接口。
動作事件監聽器
動作事件監聽器是 Swing 中比較常用的事件監聽器,很多組件的動作都會使用它監聽,像按鈕被點擊、列表框中選擇一項等。與動作事件監聽器有關的信息如下。
- 事件名稱:ActionEvent。
- 事件監聽接口: ActionListener。
- 事件相關方法:addActionListener() 添加監聽,removeActionListener() 刪除監聽。
- 涉及事件源:JButton、JList、JTextField 等。
例 1
下面以按鈕的單擊事件為例來說明動作單擊事件監聽器的應用。在此案例中統計了窗口內按鈕被單擊的次數。
本案例的核心代碼如下:
import java.awt.BorderLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.border.EmptyBorder;public class Test extends JFrame {JList list;//列表JLabel label;//標簽JButton button1;//按鈕int clicks=0;//點擊次數public Test(){setTitle("動作事件監聽器實例");//設置窗口標題setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設置關閉方式setBounds(100,100,400,200);//設置窗口大小JPanel contentPane=new JPanel();//創建面板contentPane.setBorder(new EmptyBorder(5,5,5,5));//設置面板邊框contentPane.setLayout(new BorderLayout(0,0));//設置內容面板為邊界布局setContentPane(contentPane);//應用于內容面板label=new JLabel(" ");label.setFont(new Font("楷體",Font.BOLD,16));//修改字體樣式contentPane.add(label,BorderLayout.SOUTH);//標簽放置在南部button1=new JButton("我是普通按鈕");//創建JButton對象button1.setFont(new Font("黑體",Font.BOLD,16));//修改字體樣式/*** addActionListener():添加監聽* ActionListener():事件監聽接口*/button1.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e) {label.setText("按鈕被單擊了"+(clicks++)+"次");}});contentPane.add(button1);}//處理按鈕單擊事件的匿名內部類class button1ActionListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {label.setText("按鈕被單擊了"+(clicks++)+"次");}}public static void main(String[] args) {Test test=new Test();test.setVisible(true);}}上述代碼調用 addActionListener() 方法為 button1 添加了單擊動作的事件監聽器,該監聽器由 button1ActionListener 類來實現。
button1ActionListener 類必須繼承 ActionListener 類,并重寫父類的 actionPerformed() 方法。在 actionPerformed() 方法內編寫按鈕被單擊后執行的功能。
圖 2 所示為程序運行后,沒有單擊和單擊后的效果。
在本例中使用的是內部類形式,當然也可以寫成如下形式的代碼:
焦點事件監聽器
除了單擊事件外,焦點事件監聽器在實際項目中應用也比較廣泛,例如將光標離開文本框時彈出對話框,或者將焦點返回給文本框等。
與焦點事件監聽器有關的信息如下。
- 事件名稱:FocusEvent。
- 事件監聽接口: FocusListener。
- 事件相關方法:addFocusListener() 添加監聽,removeFocusListener() 刪除監聽。
- 涉及事件源:Component 以及派生類。
FocusEvent 接口定義了兩個方法,分別為 focusGained() 方法和 focusLost() 方法,其中
- focusGained() 方法是在組件獲得焦點時執行,
- focusLost() 方法是在組件失去焦點時執行。
例 2
下面以文本框的焦點事件為例來說明焦點單擊事件監聽器的應用。本案例的核心代碼如下:
上述代碼為 txtfield1 組件調用 addFocusListener() 方法添加了焦點事件監聽器,并且監聽器使用匿名的實現方式。在實現 FocusListener 接口的代碼中編寫 focusGained() 方法和 focusLost() 方法的代碼。最終程序運行效果如圖 3 所示。
監聽列表項選擇事件
列表框控件 JList 會顯示很多項供用戶選擇,通常在使用時會根據用戶選擇的列表項完成不同的操作。
本案例將介紹如何監聽列表項的選擇事件,以及事件監聽器的處理方法,實現過程如下。
(1) 創建一個繼承自 JFrame 的 JListDemo2 類。
(2) 在 JListDemo2 類中添加 JList 組件和 JLabel 組件的聲明
import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.border.EmptyBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener;public class Test extends JFrame {JList list;JLabel label;(3) 在構造方法中為列表框填充數據源,主要代碼如下:
public Test(){setTitle("監聽列表選擇事件");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100,100,400,200);JPanel contentPane=new JPanel();contentPane.setBorder(new EmptyBorder(5,5,5,5));contentPane.setLayout(new BorderLayout(0,0));setContentPane(contentPane);label=new JLabel(" ");contentPane.add(label,BorderLayout.SOUTH);JScrollPane scrollPane=new JScrollPane();//滾動窗口contentPane.add(scrollPane,BorderLayout.CENTER);//面板里加入滾動窗口,居中list=new JList();scrollPane.setViewportView(list);//把list放入滾動窗口String[] listData=new String[10];listData[0]="加里奧";listData[1]="大發明家";listData[2]="黑默丁格";listData[3]="亞索";listData[4]="齊亞娜";listData[5]="阿卡麗";listData[6]="特朗德爾";listData[7]="賞金獵人";listData[8]="伊芙琳";listData[9]="艾克";list.setListData(listData);(4) 為列表框組件 list 添加選擇事件監聽,代碼如下所示。
list.addListSelectionListener(new ListSelectionListener() {public void valueChanged(ListSelectionEvent e){do_list_valueChanged(e);} });如上述代碼所示,list 組件綁定了 ListSelectionListener 事件監聽器,在觸發該事件后又會調用 do_list_valueChanged() 方法進行實際的業務邏輯處理。
(5) 創建 do_liSt_ValueChanged() 方法將用戶選擇的列顯示到標簽中,具體代碼如下:
protected void do_list_valueChanged(ListSelectionEvent e) {label.setText("感謝您選擇:"+list.getSelectedValue()); }完整代碼:
import java.awt.BorderLayout;import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.border.EmptyBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener;public class Test extends JFrame {JList list;JLabel label;public Test(){setTitle("監聽列表選擇事件");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100,100,400,200);JPanel contentPane=new JPanel();contentPane.setBorder(new EmptyBorder(5,5,5,5));contentPane.setLayout(new BorderLayout(0,0));setContentPane(contentPane);label=new JLabel(" ");contentPane.add(label,BorderLayout.SOUTH);JScrollPane scrollPane=new JScrollPane();//滾動窗口contentPane.add(scrollPane,BorderLayout.CENTER);//面板里加入滾動窗口,居中list=new JList();scrollPane.setViewportView(list);//把list放入滾動窗口String[] listData=new String[10];listData[0]="加里奧";listData[1]="大發明家";listData[2]="黑默丁格";listData[3]="亞索";listData[4]="齊亞娜";listData[5]="阿卡麗";listData[6]="特朗德爾";listData[7]="賞金獵人";listData[8]="伊芙琳";listData[9]="艾克";list.setListData(listData);//列表框組件 list 添加選擇事件監聽list.addListSelectionListener(new ListSelectionListener(){@Overridepublic void valueChanged(ListSelectionEvent e) {do_list_valueChanged(e);}});}//創建 do_liSt_ValueChanged() 方法將用戶選擇的列顯示到標簽中protected void do_list_valueChanged(ListSelectionEvent e) {label.setText("感謝您選擇:"+list.getSelectedValue());}public static void main(String[] args) {Test test=new Test();test.setVisible(true);} }總結
以上是生活随笔為你收集整理的13、Java Swing事件监听:事件处理模型和事件监听器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 7、Java Swing JTextAr
- 下一篇: 14、Java Swing星座选择器界面