Ch15 視窗程式設計 (2)

25
Ch15 Ch15 視視視視視視 視視視視視視 (2) (2) JAVA 視視視視視視 (2)

description

Ch15 視窗程式設計 (2). JAVA 程式語言入門 (2). 大綱. 監聽器介面 ( 參考 Ch 10) 事件轉接類別 ( 參考 Ch 10) 抽象類別 介面 多重繼承. 抽象類別 (1/3). 類別定義中,只要有一個方法(或以上)定義為 抽象方法 (abstract method),則該類別為 抽象類別 (abstract class)。 抽象方法並沒有定義方法的主體(沒有實作) 無法利用抽象類別建立物件。 抽象類別的用處是當作父類別,讓子類別繼承。 子類別必須將父類別中的抽象方法實作出來,才能建立物件。. 抽象類別 (2/3). - PowerPoint PPT Presentation

Transcript of Ch15 視窗程式設計 (2)

Page 1: Ch15  視窗程式設計 (2)

Ch15 Ch15 視窗程式設計視窗程式設計 (2)(2)JAVA 程式語言入門 (2)

Page 2: Ch15  視窗程式設計 (2)

大綱大綱監聽器介面 ( 參考 Ch 10)事件轉接類別 ( 參考 Ch 10)抽象類別介面多重繼承

Page 3: Ch15  視窗程式設計 (2)

3

抽象類別抽象類別 (1/3)(1/3)類別定義中,只要有一個方法(或以上)類別定義中,只要有一個方法(或以上)

定義為定義為抽象方法抽象方法(( abstract methodabstract method ),),則該類別為則該類別為抽象類別抽象類別(( abstract classabstract class )。)。

抽象方法並沒有定義方法的主體(沒有實抽象方法並沒有定義方法的主體(沒有實作)作)

無法利用抽象類別建立物件。無法利用抽象類別建立物件。抽象類別的用處是當作父類別,讓子類別抽象類別的用處是當作父類別,讓子類別

繼承。繼承。子類別必須將父類別中的抽象方法實作出子類別必須將父類別中的抽象方法實作出

來,才能建立物件。來,才能建立物件。

Page 4: Ch15  視窗程式設計 (2)

4

抽象類別抽象類別 (2/3)(2/3)抽象類別的定義語法:抽象類別的定義語法:

修飾字 abstract class 類別名稱{

// 屬性宣告修飾字 abstract 型別 方法名稱 ( 參數列 );// 其它方法定義

}某個類別的主體內,宣告了抽象方法,則該某個類別的主體內,宣告了抽象方法,則該

類別必須宣告為抽象類別。類別必須宣告為抽象類別。抽象類別雖然不能用以建立物件,但是可以抽象類別雖然不能用以建立物件,但是可以

當作物件的當作物件的型別型別,用來宣告參照變數。,用來宣告參照變數。抽象類別的子類別若不完全實作抽象方法,抽象類別的子類別若不完全實作抽象方法,

則依然是抽象類別。則依然是抽象類別。

Page 5: Ch15  視窗程式設計 (2)

5

抽象類別抽象類別 (3/3)(3/3)

使用抽象類別的用意,主要是「使用抽象類別的用意,主要是「制定制定固定的訊息接收管道,但不把焦點放在固定的訊息接收管道,但不把焦點放在訊息的處理上訊息的處理上」。」。

抽象類別和一般類別一樣,都抽象類別和一般類別一樣,都可以定可以定義建構子義建構子,只是不能直接以抽象類別的,只是不能直接以抽象類別的建構子建立物件。建構子建立物件。

抽象方法的目的就是為了讓子類別實抽象方法的目的就是為了讓子類別實作,所以作,所以 abstractabstract 不能同時和不能同時和 finalfinal 、、staticstatic 或 或 privateprivate 一起使用。一起使用。

Page 6: Ch15  視窗程式設計 (2)

6

單一繼承 單一繼承 vs vs 多重繼承多重繼承 (1/2)(1/2)

Java 的繼承是屬於單一繼承, C++ 的繼承是屬於多重繼承

多重繼承是指:指一個類別能夠繼承多個父類別

在許多時候多重繼承的性質是相當有用。

在 Java ,多重繼承的性質交給介面。

Page 7: Ch15  視窗程式設計 (2)

7

單一繼承 單一繼承 vs vs 多重繼承多重繼承 (2/2)(2/2)多重繼承的性質很有用,現實環境中,

處處是多重繼承,想想以下情境:你有一隻手機,它有 PDA 和 GPS 的功能,

有一天, ToTo 跟你借 GPS如果 1 :你怕 ToTo 弄壞了,他的媽媽又不

會賠,這時,你可以採用『單一繼承』的說法, “不好意思,我有行動電話”

如果 2 :你不怕 ToTo 弄壞,因為他弄壞了,你就可以順理成章的成為他的小童星經紀人,好好利用他大賺一筆;則,你可以採用『多重繼承』的說法, “我有一隻手機,它有GPS 的功能,借給你”

Page 8: Ch15  視窗程式設計 (2)

8

介面介面 (1/2)(1/2)

介面中定義的方法就像是飲料販賣機上的按鈕

Page 9: Ch15  視窗程式設計 (2)

9

介面介面 (2/2)(2/2)介面( Interface )是在類別繼承架構

中定義類別行為,內含常數和方法宣告,但是並沒有實作程式碼

Page 10: Ch15  視窗程式設計 (2)

10

介面的定義與實作介面的定義與實作 (1/3)(1/3)

定義介面的語法:修飾字 interface 介面名稱{ // 靜態常數定義 // 抽象方法宣告}

介面定義的例子:interface MyInterface{ int i=2;    // 已預設使用 public 、 final 、 static void m(); // 已預設使用 public 、 abstract}

Page 11: Ch15  視窗程式設計 (2)

11

介面的定義與實作介面的定義與實作 (2/3)(2/3)

實作介面的類別定義語法:修飾字 class 類別名稱 implements 介面名

稱{

// 包含實作方法的敘述}

Page 12: Ch15  視窗程式設計 (2)

12

介面的定義與實作介面的定義與實作 (3/3)(3/3)

介面多重繼承的語法:interface 子介面 extends 父介面一 , 父介面二 , ...{

// 新增的靜態常數及抽象方法}

類別實作多個介面的語法:class 類別名稱 implements 介面一 , 介面二 , ...{

// 類別主體敘述}

Page 13: Ch15  視窗程式設計 (2)

13

範例範例 1:1: 宣告與使用介面宣告與使用介面 (1/4)(1/4)

UML 類別圖,如下圖所示:

Page 14: Ch15  視窗程式設計 (2)

14

範例範例 1:1: 宣告與使用介面宣告與使用介面 (2/4)(2/4)AreaInterface 介面,如下所示:

interface AreaInterface{ final double PI = 3.1415926; void area();}

Page 15: Ch15  視窗程式設計 (2)

15

範例範例 1:1: 宣告與使用介面宣告與使用介面 (3/4)(3/4)

接著 Circle 類別可以實作這個介面,如下所示:class Circle extends Shape implements

AreaInterface{ ……… public void area() { System.out.println("X 座標 : " + x); System.out.println("Y 座標 : " + y); System.out.println(" 圓半徑 : " + r); System.out.println(" 圓面積 : " + PI*r*r); } }

Page 16: Ch15  視窗程式設計 (2)

16

範例範例 1:1: 宣告與使用介面宣告與使用介面 (4/4)(4/4)1. abstract class Shape06012. { public double x;3. public double y;4. }5. interface AreaInterface06016. { final double PI = 3.1415926;7. void area();8. }9. class Circle0601 extends Shape0601 implements

AreaInterface060110. { public double r;11. public Circle0601(double x, double y, double r)12. { this.x = x;13. this.y = y;14. this.r = r;15. }16. public void area()17. { System.out.println("X 座標 : " + x);18. System.out.println("Y 座標 : " + y);19. System.out.println(" 圓半徑 : " + r);20. System.out.println(" 圓面積 : " + PI*r*r);21. }22. }

1. class Ch06_012. { public static void main(String [] args)3. {4. Circle0601 c = new Circle0601(5.0,

5.0, 8.0);5. c.area();6. System.out.println("PI 常數 : " +

AreaInterface0601.PI);7. System.out.println("PI 常數 ( 以物件方

式 ): " + c.PI); 8. }9. }

Page 17: Ch15  視窗程式設計 (2)

MouseListenerMouseListener import javax.swing.*; // 引用 Swing 套件 import java.awt.*;

import java.awt.event.*; // 引用處理事件的 event 套件

public class MouseEX extends JFrame {

JButton clickME = new JButton(" 請按我 !"); // 建立元件 JLabel lbMouse = new JLabel(" 滑鼠事件訊息 "), // 建立顯示訊息的標籤 lbMouseButton = new JLabel(" 按下按鍵 ");

// 以匿名類別的方式實作 MouseListener 介面 ,

// 宣告回應滑鼠事件的監聽器 MouseListener mlBtn = new MouseListener() {

private int clickCount = 0, // 記錄按鈕被按下次數的屬性 doubleClickCount = 0; // 記錄按鈕被按下次數的屬性

Page 18: Ch15  視窗程式設計 (2)

// 處理按一下滑鼠按鍵動作的方法 public void mouseClicked(MouseEvent e) {

if(e.getClickCount() == 2)

doubleClickCount++;

((JButton) e.getSource()).setText(" 按下一下 : " +

(clickCount++) + " 次 | 連按兩次 : " + doubleClickCount + " 次 ");

}

// 處理滑鼠游標進入元件的方法 public void mouseEntered(MouseEvent e) {

((JButton) e.getSource()).setText(" 滑鼠游標進入按鈕範圍 ");

}

// 處理滑鼠游標離開元件的方法 public void mouseExited(MouseEvent e) {

((JButton) e.getSource()).setText(" 滑鼠游標離開按鈕範圍 ");

}

Page 19: Ch15  視窗程式設計 (2)

// 處理按下滑鼠按鍵動作的方法 public void mousePressed(MouseEvent e){

switch(e.getButton()){ // 取得滑鼠被按下的按鍵 case MouseEvent.BUTTON1 :

lbMouseButton.setText(" 滑鼠左鍵被按下 ");

break;

case MouseEvent.BUTTON2 :

lbMouseButton.setText(" 滑鼠中間鍵被按下 ");

break;

case MouseEvent.BUTTON3 :

lbMouseButton.setText(" 滑鼠右鍵被按下 ");

break;

case MouseEvent.NOBUTTON :

lbMouseButton.setText(" 沒有滑鼠按鍵被按下 ");

break;

}

}

// 處理放開滑鼠按鍵動作的方法 // 即使不處理事件但仍須定義空的回應方法 public void mouseReleased(MouseEvent e){ }

};

Page 20: Ch15  視窗程式設計 (2)

// 以匿名類別的方式實作 MouseMotionListener 介面 ,

// 宣告回應滑鼠事件的監聽器 MouseMotionListener mmlFrame = new MouseMotionListener(){

public void mouseDragged(MouseEvent e){ // 滑鼠拖曳 lbMouse.setText(" 滑鼠在視窗範圍內 [ 拖曳 ] , 游標位置在 ( "

+ e.getX() + ", " + e.getY() + " )");

}

public void mouseMoved(MouseEvent e){ // 滑鼠移動 lbMouse.setText(" 滑鼠在視窗範圍內 [ 移動 ] , 游標位置在 ( "

+ e.getX() + ", " + e.getY() + " )");

}

};

MouseEX(){

Box bxBtn = new Box(BoxLayout.X_AXIS);

bxBtn.add(Box.createHorizontalGlue());

bxBtn.add(clickME); //加入按鈕元件 bxBtn.add(Box.createHorizontalGlue());

Container cp = getContentPane(); // 取得內容面版

Box bxLabel = new Box(BoxLayout.Y_AXIS);

Page 21: Ch15  視窗程式設計 (2)

bxLabel.add(lbMouse); // 將標籤元件加入 Box容器 bxLabel.add(Box.createVerticalStrut(10));

bxLabel.add(lbMouseButton);

cp.add(bxBtn); // 將包含按鈕元件的 Box容器加入內容面版 cp.add(bxLabel, BorderLayout.SOUTH);

// 將包含標籤元件的 Box容器加入面版 clickME.addMouseListener(mlBtn);

//註冊由mlBtn 監聽 clickME 元件的滑鼠事件

addMouseMotionListener(mmlFrame);

//註冊由mmlFrame 監聽視窗的滑鼠移動事件

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(300, 250);

setVisible(true);

}

public static void main(String args[]) {

new MouseEX(); //產生視窗框架物件 }

}

Page 22: Ch15  視窗程式設計 (2)

MouseAdapterMouseAdapter import javax.swing.*; // 引用 Swing 套件 import java.awt.*;

import java.awt.event.*; // 引用處理事件的 event 套件

public class AdapterEX extends JFrame{

JButton clickME = new JButton(" 請按我 !"); // 建立元件 JLabel lbPos = new JLabel(" 顯示滑鼠相關訊息 ");

MouseListener mlFrame = new MouseListener(){

public void mouseClicked(MouseEvent e){

lbPos.setText(" 在 (" + e.getX() + ", " + e.getY() + ") 按下滑鼠 ");

}

public void mouseEntered(MouseEvent e){

lbPos.setText(" 滑鼠游標進入視窗 ");

}

public void mouseExited(MouseEvent e){

lbPos.setText(" 滑鼠游標離開視窗 ");

}

Page 23: Ch15  視窗程式設計 (2)

// 即使不處理事件但仍須定義空的回應方法 public void mousePressed(MouseEvent e){ }

public void mouseReleased(MouseEvent e){ }

};

//運用匿名內部類別 , 以繼承 MouseAdaptor 的方式定義監聽器類別 , 並完成宣告 MouseAdapter maBtn = new MouseAdapter(){

int clickCount = 0; // 記錄按鈕被按下次數的屬性

public void mouseClicked(MouseEvent e){

((JButton) e.getSource()).setText(

"按鈕被按了 " + (clickCount++) + " 次 ");

}

public void mouseEntered(MouseEvent e){

((JButton) e.getSource()).setText(" 滑鼠游標進入按鈕範圍 ");

}

public void mouseExited(MouseEvent e){

((JButton) e.getSource()).setText(" 滑鼠游標離開按鈕範圍 ");

}

};

Page 24: Ch15  視窗程式設計 (2)

AdapterEX(){

Container cp = getContentPane(); // 取得內容面版

Box bxBtn = new Box(BoxLayout.X_AXIS);

bxBtn.add(Box.createHorizontalGlue());

bxBtn.add(clickME); // 將元件加入 Box容器 bxBtn.add(Box.createHorizontalGlue());

cp.add(bxBtn); // 將 Box容器加入內容面版 cp.add(lbPos, BorderLayout.SOUTH);

clickME.addMouseListener(maBtn);

//註冊由maBtn 監聽 clickME 元件的滑鼠事件

addMouseListener(mlFrame);

//註冊由mlFrame 監聽視窗的滑鼠事件

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(200, 150);

setVisible(true);

}

Page 25: Ch15  視窗程式設計 (2)

public static void main(String args[]) {

new AdapterEX(); //產生視窗框架物件 }

}