1. 程式人生 > >java丨事件驅動程式設計學習筆記(一)

java丨事件驅動程式設計學習筆記(一)

一、事件和事件源

事件:事件可以定義為程式發生了某些事情的訊號 源物件(源元件):能建立一個事件並觸發該事件的元件成為源物件 事件類的根類:java.util.EventObject 可以使用EventObject類中的例項方法getSource()獲得事件的源物件 如果一個元件可以觸發某個事件,那麼這個事件的任意子類都可以觸發同類型的事件,如因為GUI元件的父類Component可以觸發MouseEvent、KeyEvent、FocusEvent和ComponentEvent,所以任意的GUI元件都可以觸發上述事件 二、監聽器、註冊以及處理事件 java使用一種基於委託的模型來處理事件:源物件觸發一個事件,對此事件感興趣的物件會處理它。將對此事件感興趣的物件稱為監聽器。 一個物件要稱為源物件上的事件監聽器,需要具備兩個條件: (1)監聽器物件的類必須是相應的事件監聽器介面的例項,以確保監聽器有處理這個事件的正確方法。 (2)監聽器物件必須由源物件註冊。註冊方法依賴於事件的型別。 下面我們編寫一個程式,使用兩個按鈕控制一個圓的大小

ControlCircle1.java

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

public class ControlCircle1 extends JFrame{
    private JButton jbtEnlarge = new JButton("Enlarge");
    private JButton jbtShrink = new JButton("Shrink");
    private CirclePanel canvas = new CirclePanel();
    public ControlCircle1(){
    JPanel panel = new JPanel();//Use the panel to group buttons
    //將兩個按鈕新增到面板中
    panel.add(jbtEnlarge);
    panel.add(jbtShrink);

    this.add(canvas,BorderLayout.CENTER);//將畫布新增到中央
    this.add(panel,BorderLayout.SOUTH);//將裝有兩個按鈕的面板新增到SOUTH的位置
    }
    public static void main(String[] args){
    JFrame frame = new ControlCircle1();
    frame.setTitle("ControlCircle1");
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(200,200);
    frame.setVisible(true);
    }
}
class CirclePanel extends JPanel{
private int radius = 5;//預設的圓的半徑

/**repaint the circle */
protected void paintComponent(Graphics g){
    super.paintComponent(g);
    g.drawOval(getWidth()/2-radius,getHeight()/2-radius,2*radius,2*radius);
    }
}

得到了圖形介面

在完成了圖形介面設計之後,我們要實現通過按鈕來控制圓的大小 如何使用按鈕放大和縮小這個圓呢?當點選Enlarge按鈕時,希望能用一個比較大的半徑來重新繪製這個圓,如何實現?

(1)定義名為EnlargeListener和ShrinkListener的監聽器類,實現ActionListener (2)建立兩個監聽器,並且將它註冊到jbtEnlarge和jbtShrink (3)在CirclePanel中新增一個名為enlarge()的方法來增加半徑,新增一個名為shrink()的方法來縮小半徑,然後重新繪製面板 (4)實現EnlargeListener中的actionPerformed方法來呼叫canvas.enlarge()和canvas.shrink() (5)為了讓actionPerformed方法可以訪問引用變數canvas,將EnlargeListener定義為ControlCircle2類的內部類。內部類定義在另一個類中。 (6)為了避免編譯錯誤,CirclePanel類現在也定義為ControlCircle2的一個內部類 以下程式碼實現了通過Enlarge按鈕放大圓,通過Shrink按鈕縮小圓

ControlCircle2.java

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

public class ControlCircle2 extends JFrame{
    private JButton jbtEnlarge = new JButton("Enlarge");
    private JButton jbtShrink = new JButton("Shrink");
    private CirclePanel canvas = new CirclePanel();

    public ControlCircle2(){
        JPanel panel = new JPanel();//use the panel to group buttons
        panel.add(jbtEnlarge);
        panel.add(jbtShrink);

        this.add(canvas,BorderLayout.CENTER);
        this.add(panel,BorderLayout.SOUTH);

        jbtEnlarge.addActionListener(new EnlargeListener());
        jbtShrink.addActionListener(new ShrinkListener());
        }
        /**Main Method**/
        public static void  main(String[] args){
            JFrame frame = new ControlCircle2();
            frame.setTitle("ControlCircle2");
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(400,400);
            frame.setVisible(true);
        }

        //定義一個名為EnlargeListener的監聽器類,實現ActionListener
        class EnlargeListener implements ActionListener{
            public void actionPerformed(ActionEvent e){
            canvas.enlarge();
         }
        }
        //定義一個名為ShrinkListener的監聽器類,實現ActionListener
        class ShrinkListener implements ActionListener{
            public void actionPerformed(ActionEvent e) {
                canvas.shrink();
            }
        }
        class CirclePanel extends JPanel{
           private int radius = 5;//預設圓的半徑為5
           /**Enlarge the circle */
           public void enlarge(){
               radius++;
               repaint();
           }
           public void shrink() {
               radius--;
               repaint();
           }
           /**repaint the circle */
           protected void paintComponent(Graphics g){
               super.paintComponent(g);
               g.drawOval(getWidth()/2-radius,getHeight()/2-radius,2*radius,2*radius);
               }
              }  
}

原始、放大、縮小

三、內部類 內部類或者巢狀類是定義在另一個類的範圍內的類 兩個獨立的類:

public class Test{
    ...
}
public class A{
    ...
}
public class Test{
    ...
    //inner class 
    public class A{
    ...
    }
}

內部類可以像常規類一樣使用。如果內部類只是被外部類使用,那就將該類定義為內部類。 一個內部類有如下的特徵: (1)一個內部類被編譯成一個名為OuterClassNameInnerlClassName.class的類。例如:Test中的A被編譯為TestInnerlClassName.class的類。例如:Test中的A被編譯為TestA.class。 (2)內部類可以引用定義在它巢狀的外部類中的資料和方法,所以,不需要將外部類物件的引用傳遞給內部類的構造方法。因此,內部類可以使程式更加簡單和簡潔 (3)使用可見性修飾符定義內部類時,遵從和應用與在類成員上一樣的可見性規則, (4)可以將內部類定義為static。一個static內部類可以使用外部類的名字訪問。一個static類是不能訪問外部類的非靜態成員的。 (5)內部類的物件經常在外部類中建立。但是,也可以從另一個類中建立一個內部類的物件。如果該內部類是非靜態的,那就必須先建立一個外部類的例項,然後使用下面的語法建立一個內部類的物件: OuterClass.InnerClass innerObject = outerObject.new InnerClass(); 如果內部類是靜態的,那麼使用下面的語法為它建立一個物件: OuterClass.InnerClass innerObject = new OuterClass.InnerClass(); 內部類的一個簡單應用就是將從屬類合併到主類中。這可以減少原始檔的數量。例如,將類A合併到類Test中,只建立一個原始檔Test.java,最終的類檔案是Test.class和Test$A.class 內部類的另一個實際應用是為了避免類命名衝突