Java-GUI編程之事件處理

事件處理

前面介紹了如何放置各種組件,從而得到了豐富多彩的圖形界面,但這些界面還不能響應用戶的任何操作。比如單擊前面所有窗口右上角的「X」按鈕,但窗口依然不會關閉。因為在 AWT 編程中 ,所有用戶的操作,都必須都需要經過一套事件處理機制來完成,而 Frame 和組件本身並沒有事件處理能力 。

GUI事件處理機制

定義:

​ 當在某個組件上發生某些操作的時候,會自動的觸發一段代碼的執行。

在GUI事件處理機制中涉及到4個重要的概念需要理解:

事件源(Event Source) :操作發生的場所,通常指某個組件,例如按鈕、窗口等;
事件(Event):在事件源上發生的操作可以叫做事件,GUI會把事件都封裝到一個Event對象中,如果需要知道該事件的詳細信息,就可以通過Event對象來獲取。
事件監聽器(Event Listener):當在某個事件源上發生了某個事件,事件監聽器就可以對這個事件進行處理。

註冊監聽:把某個事件監聽器(A)通過某個事件(B)綁定到某個事件源(C)上,當在事件源C上發生了事件B之後,那麼事件監聽器A的代碼就會自動執行。



使用步驟:

1.創建事件源組件對象;

2.自定義類,實現XxxListener接口,重寫方法;

3.創建事件監聽器對象(自定義類對象)

4.調用事件源組件對象的addXxxListener方法完成註冊監聽

案例:

​ 完成下圖效果,點擊確定按鈕,在單行文本域內顯示 hello world:



import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class EventDemo1 {
    Frame  frame = new Frame("這裡測試事件處理");

    //事件源
    Button button = new Button("確定");

    TextField tf = new TextField(30);
    public void init(){
        //註冊監聽
        button.addActionListener(new MyActionListener());

        //添加組件到frame中
        frame.add(tf);
        frame.add(button,BorderLayout.SOUTH);

        //設置frame最佳大小並可見
        frame.pack();
        frame.setVisible(true);
    }

    //自定義事件監聽器類
    private  class MyActionListener implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {

            System.out.println("用戶點擊了確定按鈕");
            tf.setText("hello world");
        }
    }
    
    public static void main(String[] args) {
        new EventDemo1().init();
    }
}

GUI中常見事件和事件監聽器

事件監聽器必須實現事件監聽器接口, AWT 提供了大量的事件監聽器接口用於實現不同類型的事件監聽器,用於監聽不同類型的事件 。 AWT 中提供了豐富的事件類,用於封裝不同組件上所發生的特定操作, AWT 的事件類都是 AWTEvent 類的子類 , AWTEvent是 EventObject 的子類。

事件

AWT把事件分為了兩大類:

​ 1.低級事件:這類事件是基於某個特定動作的事件。比如進入、點擊、拖放等動作的鼠標事件,再比如得到焦點和失去焦點等焦點事件。

事件 觸發時機
ComponentEvent 組件事件 , 當 組件尺寸發生變化、位置發生移動、顯示/隱藏狀態發生改變時觸發該事件。
ContainerEvent 容器事件 , 當容器里發生添加組件、刪除組件時觸發該事件 。
WindowEvent 窗口事件, 當窗 口狀態發生改變 ( 如打開、關閉、最大化、最 小化)時觸發該事件 。
FocusEvent 焦點事件 , 當組件得到焦點或失去焦點 時觸發該事件 。
KeyEvent 鍵盤事件 , 當按鍵被按下、鬆開、單擊時觸發該事件。
MouseEvent 鼠標事件,當進行單擊、按下、鬆開、移動鼠標等動作 時觸發該事件。
PaintEvent 組件繪製事件 , 該事件是一個特殊的事件類型 , 當 GUI 組件調 用 update/paint 方法 來呈現自身時觸發該事件,該事件並非專用於事件處理模型 。

​ 2.高級事件:這類事件並不會基於某個特定動作,而是根據功能含義定義的事件。

事件 觸發時機
ActionEvent 動作事件 ,當按鈕、菜單項被單擊,在 TextField 中按 Enter 鍵時觸發
AjustmentEvent 調節事件,在滑動條上移動滑塊以調節數值時觸發該事件。
ltemEvent 選項事件,當用戶選中某項, 或取消選中某項時觸發該事件 。
TextEvent 文本事件, 當文本框、文本域里的文本發生改變時觸發該事件。

事件監聽器

不同的事件需要使用不同的監聽器監聽,不同的監聽器需要實現不同的監聽器接口, 當指定事件發生後 , 事件監聽器就會調用所包含的事件處理器(實例方法)來處理事件 。

事件類別 描述信息 監聽器接口名
ActionEvent 激活組件 ActionListener
ItemEvent 選擇了某些項目 ItemListener
MouseEvent 鼠標移動 MouseMotionListener
MouseEvent 鼠標點擊等 MouseListener
KeyEvent 鍵盤輸入 KeyListener
FocusEvent 組件收到或失去焦點 FocusListener
AdjustmentEvent 移動了滾動條等組件 AdjustmentListener
ComponentEvent 對象移動縮放顯示隱藏等 ComponentListener
WindowEvent 窗口收到窗口級事件 WindowListener
ContainerEvent 容器中增加刪除了組件 ContainerListener
TextEvent 文本字段或文本區發生改變 TextListener

案例

案例一:

​ 通過ContainerListener監聽Frame容器添加組件;

​ 通過TextListener監聽TextFiled內容變化;

​ 通過ItemListener監聽Choice條目選中狀態變化;



import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ListenerDemo1 {
    public static void main(String[] args) {
        Frame frame = new Frame("這裡測試監聽器");

        // 創建組件(事件源)
        TextField tf = new TextField(30);
        Choice names = new Choice();
        names.add("柳岩");
        names.add("舒淇");
        names.add("閆妮");

        // 給文本域添加TextListener,監聽內容的變化
        tf.addTextListener(new TextListener() {
            @Override
            public void textValueChanged(TextEvent e) {
                String text = tf.getText();
                System.out.println("當前文本框中的內容為:" + text);
            }
        });

        // 給下拉選擇框添加ItemListener,監聽條目選項的變化
        names.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                Object item = e.getItem();
                System.out.println("當前選中的條目為:" + item);
            }
        });

        // 給frame註冊ContainerListener監聽器,監聽容器中組件的添加
        frame.addContainerListener(new ContainerListener() {
            @Override
            public void componentAdded(ContainerEvent e) {
                Component child = e.getChild();
                System.out.println("frame中添加了:" + child);
            }

            @Override
            public void componentRemoved(ContainerEvent e) {

            }
        });

        // 添加到frame中
        Box hBox = Box.createHorizontalBox();
        hBox.add(names);
        hBox.add(tf);
        frame.add(hBox);

        // 設置frame最佳大小並可見
        frame.pack();
        frame.setVisible(true);
    }
}

案例2:

​ 給Frame設置WindowListner,監聽用戶點擊 X 的動作,如果用戶點擊X,則關閉當前窗口

演示代碼2:

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class ListenerDemo2 {

    public static void main(String[] args) {

        Frame frame = new Frame("這裡測試WindowListener");

        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        frame.setBounds(200,200,500,300);

        frame.setVisible(true);
    }
}

公眾號文章地址://mp.weixin.qq.com/s/0BOBUP2pFrizTJ4mZNQP6w

個人博客://kohler19.gitee.io/
公眾號:愚生淺末