ch16 繪圖與多媒體

63
Ch16 繪繪繪繪繪JAVA 繪繪繪繪繪繪 (II)

Upload: jerry

Post on 13-Jan-2016

137 views

Category:

Documents


0 download

DESCRIPTION

Ch16 繪圖與多媒體. JAVA 程式設計入門 (II). 大綱. 繪圖的基礎 Graphics 類別的色彩、文字與繪圖 圖片的載入與顯示 動畫效果 Java Applet 的圖片載入 音樂的播放. Graphics 繪圖類別 - 取得 Graphics 繪圖類別. 在 Java Applet 程式範例已經說明過 paint() 方法繪出文字和簡單圖形,使用的是 Graphics 類別的方法。 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Ch16  繪圖與多媒體

Ch16 繪圖與多媒體

JAVA程式設計入門 (II)

Page 2: Ch16  繪圖與多媒體

112/04/21 2

大綱

• 繪圖的基礎• Graphics類別的色彩、文字與繪圖• 圖片的載入與顯示• 動畫效果• Java Applet的圖片載入• 音樂的播放

Page 3: Ch16  繪圖與多媒體

112/04/21 3

Graphics繪圖類別 -取得 Graphics繪圖類別

• 在 Java Applet程式範例已經說明過 paint()方法繪出文字和簡單圖形,使用的是Graphics類別的方法。

• 在 Java執行繪圖功能需要使用「圖形內容」( Graphics Contexts)的 Graphics物件,繪製的文字、影像和圖形都是繪製在此畫布物件上,如同將 GUI元件新增到JFrame物件的 ContentPane物件一般。

Page 4: Ch16  繪圖與多媒體

112/04/21 4

範例 1:使用 Applet呈現圖• Ch11_10.java1. import java.applet.Applet;2. import java.awt.*;

3. public class Ch11_10 extends Applet4. {5. public void paint(Graphics g)6. {7. setBackground(Color.lightGray);8. g.setColor(Color.red);9. g.fillRect(10,10,100, 100);10. }11. }

• Ch11_10.html1. <HTML>2. <head>3. <title>Ch11_10.html</title>4. </head>5. <body>6. <hr>7. <center>8. <applet9. code = Ch11_10.class10. width = 20011. height = 20012. >13. </applet>14. </center>15. <hr>16. </body>17.</html>

Page 5: Ch16  繪圖與多媒體

112/04/21 5

Graphics繪圖類別 -paint()方法

• 繼承自 Component元件的 paint()方法在呼叫時,其傳入參數就是 Graphics物件,如下所示:public void paint(Graphics g)

{ ……… }

• 在上述的 paint()方法呼叫繪圖方法,就可以在元件上繪出圖形。

Page 6: Ch16  繪圖與多媒體

112/04/21 6

範例 2:使用 JFrame類別的畫布1. import javax.swing.*;2. import java.awt.*;3. import java.awt.event.*;

4. class Ch11_11 extends JFrame5. {6. Ch11_11()7. {8. super("JFrame畫布 ");9. Container c = getContentPane();10. c.setBackground(Color.lightGray);11. }

12. public void paint(Graphics g)13. {14. g.setColor(Color.red);15. g.fillRect(10, 10, 100, 100);16. }

17. public static void main(String [] args)18. {19. // 建立 Swing應用程式20. Ch11_11 app = new Ch11_11();

21. // 關閉視窗事件 , 結束程式的執行22. app.addWindowListener(new WindowAdapter()23. { public void windowClosing(WindowEvent evt)24. { System.exit(0); }25. });26. app.setSize(300,200); // 設定尺寸27. app.setVisible(true); // 顯示視窗28. }29. }

Page 7: Ch16  繪圖與多媒體

112/04/21 7

Graphics繪圖類別 -getGraphics()方法

• 在 paint()方法之外的其它方法執行繪圖,可以使用 getGraphics()方法取得元件的Graphics物件,如下所示:Graphics g = app.getGraphics();

• 上述程式碼取得 app元件的 Graphics物件,接著就可以呼叫繪圖方法在元件上繪出圖形。

Page 8: Ch16  繪圖與多媒體

112/04/21 8

範例 3:使用 getGraphics()1. import javax.swing.*;2. import java.awt.*;3. import java.awt.event.*;

4. class Ch11_12 extends JFrame5. {6. Ch11_12()7. {8. super("JFrame畫布 ");9. Container c = getContentPane();10. c.setBackground(Color.lightGray);11. }

12. public static void main(String [] args)13. {14. // 建立 Swing應用程式15. Ch11_12 app = new Ch11_12();

16. // 關閉視窗事件 , 結束程式的執行17. app.addWindowListener(new WindowAdapter()18. { public void windowClosing(WindowEvent evt)19. { System.exit(0); }20. });21. app.setSize(300,200); // 設定尺寸22. app.setVisible(true); // 顯示視窗

23. //利用 getGraphics()取得 Graphics Context24. Graphics g = app.getGraphics();25. g.setColor(Color.red);26. g.fillRect(10, 10, 100, 100);27. }28. }

Page 9: Ch16  繪圖與多媒體

112/04/21 9

Graphics繪圖類別 -Swing 的 paintComponent()方法

• 對於繼承自 Swing元件的類別。例如: JPanel建立的畫布時,繪圖方法的程式碼是位於覆寫的paintComponent()方法,如下所示:class UserPanel extends JPanel

{ // 建構子 public UserPanel()

{ ……… }

public void paintComponent(Graphics g)

{ ……… }

}

Page 10: Ch16  繪圖與多媒體

112/04/21 10

範例 4: JPanel類別的畫布1. import javax.swing.*;2. import java.awt.*;3. import java.awt.event.*;

4. class Ch11_13 extends JFrame5. {6. GraphicPanel gPanel = new GraphicPanel();7. Ch11_13()8. {9. super("JPanel畫布 ");10. Container c = getContentPane();11. c.setLayout(new FlowLayout());12. c.setBackground(Color.lightGray);13. c.add(gPanel);14. Graphics g = gPanel.getGraphics();15. repaint();16. }

17. class GraphicPanel extends JPanel18. {19. GraphicPanel()20. {21. setPreferredSize(new Dimension(200,150));22. }23. public void painComponent(Graphics g)24. {25. super.paintComponent(g);26. g.setColor(Color.red);27. g.fillRect(10, 10, 100, 100);28. }29. }

30. public static void main(String [] args)31. {32. // 建立 Swing應用程式33. Ch11_13 app = new Ch11_13();

34. // 關閉視窗事件 , 結束程式的執行35. app.addWindowListener(new WindowAdapter()36. { public void windowClosing(WindowEvent evt)37. { System.exit(0); }38. });39. app.setSize(300,200); // 設定尺寸40. app.setVisible(true); // 顯示視窗41. }42. }

Page 11: Ch16  繪圖與多媒體

112/04/21 11

Graphics繪圖類別 -再談 paint() 和 repaint()方法

• Swing元件屬於 JComponent的子類別,同時繼承 Component 的 paint() 和 repaint()方法,因為元件繪圖操作大都是呼叫paint()方法完成, paint()方法非常總明,能夠在使用者調整視窗尺寸(例如:縮小和放大元件的視窗)等操作後,或是執行setText()等方法改變元件內容時,自動重新呼叫 repaint()方法重繪調整後的圖形和元件。

Page 12: Ch16  繪圖與多媒體

112/04/21 12

座標系統與 JComponent元件 -說明

• 電腦螢幕的座標系統是使用「像素」( Pixels)為單位, Graphics物件的畫布是一張長方形區域,左上角為原點,其座標是 (0, 0) , X軸從左到右,Y軸由上到下,如下圖所示:

Page 13: Ch16  繪圖與多媒體

112/04/21 13

座標系統與 JComponent元件 -取得尺寸

• 座標系統可以使用 JComponent元件的getWidth() 、 getHeight()方法取得元件的寬和高,因為元件的四周預設有邊線,所以需要使用 getInsets()取得邊線left 、 right 、 top 和 bottom的尺寸,如下所示:Insets ins = getInsets();int width = getWidth() - (ins.left + ins.right);int height = getHeight() - (ins.top + ins.bottom);

Page 14: Ch16  繪圖與多媒體

112/04/21 14

JFrame類別的畫布 -說明• Java應用程式可以將整個 JFrame視窗或某個 Swing元件作為畫布,如果是 JFrame畫布,只需在 paint()方法撰寫繪圖方法的程式碼,就可以在視窗繪出所需圖形。

Page 15: Ch16  繪圖與多媒體

112/04/21 15

JFrame類別的畫布 -繪圖• 如果不是在 paint()方法, Java程式碼需要使用 getGraphics()方法取得 Grphics物件後,在 Graphics物件繪出所需圖形,如下所示:Graphics g = app.getGraphics();

g.setColor(Color.green);

g.fillOval(100, 100, 40, 40);

Page 16: Ch16  繪圖與多媒體

112/04/21 16

JPanel類別的畫布

• Swing 的 JPanel元件可以取代 AWT 的Canvas類別畫布, JPanel預設提供「雙緩衝區」( Double Buffering)繪圖功能,所有元件的繪圖都是在幕後完成後,才會一次顯示到螢幕上,所以可以加速圖形的顯示。

Page 17: Ch16  繪圖與多媒體

112/04/21 17

指定色彩 -建立 Color物件• Java色彩是 java.awt.Color 的 Color物件,這是使用 RGB色彩以不同程度的紅、綠和藍 3原色混合出的 Color色彩物件,如下所示:Color myColor = new Color(r, g, b);

• 上述參數 r 、 g 和 b如為 int整數,其範圍是 0~255,如為 float 是 0.0~1.0。

Page 18: Ch16  繪圖與多媒體

112/04/21 18

指定色彩 -指定色彩方法• 在建立好 Color物件後,可以使用

Graphics類別的方法指定色彩,相關方法如下表所示:

方法 說明void setColor(Color) 設定色彩為參數的 Color物件

Color getColor() 取得目前的 Color物件

Page 19: Ch16  繪圖與多媒體

112/04/21 19

指定字型 -建立 Font物件• Java的字型是 java.awt.Font 的 Font物件,這是代表指定尺寸和樣式的字型,如下所示:Folot myFont = new Font("新細明體 ",

Font.PLAIN, 30);

• 上述參數分別是字型名稱、樣式和尺寸。

Page 20: Ch16  繪圖與多媒體

112/04/21 20

指定字型 -指定字型方法• 在建立好 Font物件後,可以使用 Graphics類別的方法指定字型,相關方法如下表所示:

方法 說明void setFont(Font) 設定字型為參數的 Font物件

Font getFont() 取得目前使用的 Font物件

Page 21: Ch16  繪圖與多媒體

112/04/21 21

字型定位尺寸 FontMetrics-說明

• FontMetrics物件可以取得字串和字型細部定位尺寸,以便在畫布上能夠準確編排文字內容,相關字型的細部尺寸,如下圖所示:

Page 22: Ch16  繪圖與多媒體

112/04/21 22

字型定位尺寸 FontMetrics-相關方法

• FontMetrics類別的相關方法,如下表所示:

方法 說明FontMetrics getFontMetrics(Font) 取得參數 Font物件的 FontMetrics物

件Font getFont() 取得 FontMetrics物件定義的 Font字

型int getAscent() 取得基線上方的尺寸int getDescent() 取得基線下方的尺寸int getLeading() 取得頂端線間的高度int getHeight() 取得字型高度

int stringWidth(String) 取得參數 String字串的寬度

Page 23: Ch16  繪圖與多媒體

112/04/21 23

圖形和字串的繪圖方法 -1

• Graphics類別提供多種方法可以繪出線條、長方形、圓邊長方形、圓形或橢圓形,如下表所示:

方法 說明void drawString(String, int, int) 顯示參數 String的字串內容,後 2個參

數 int為文字內容的位置座標(x, y)

void drawLine(int, int, int, int) 使用目前色彩繪出線條,4個參數分別為起點的(x, y)和終點的(x1, y1)

void drawRect(int, int, int, int) 使用目前色彩繪出長方形,前 2個參數 int

是左上角座標(x, y),後 2個參數分別為長方形的寬和高

void draw3DRect(int, int, int, int,boolean)

繪出 3D效果的長方形,前 2個參數 int

是左上角座標(x, y),後 2個分別為長方形的寬和高,最後的 boolean參數決定長方形是凸出還是凹下表面,true是凸出

Page 24: Ch16  繪圖與多媒體

112/04/21 24

圖形和字串的繪圖方法 -2

void drawRoundRect(int, int, int,int, int, int)

繪出圓角長方形,前 2個參數 int是左上角座標(x, y),接著 2個分別為長方形的寬和高,最後 2個參數 int決定圓角弧度

的水平和垂直尺寸void drawOval(int, int, int, int) 繪出圓形或橢圓形,這個圓形是位在長

方形的範圍內,前 2個參數 int是左上角座標(x, y),最後 2個分別為長方形的寬

和高void drawArc(int ,int, int, int, int,

int)繪出一段弧形,弧形是位在長方形的範圍內,前 2個參數 int是左上角座標(x, y),接著 2個分別為長方形的寬和高,最後 2

個參數 int是從第 1個 int的角度開始(時鐘的 3點位置是 0),到最後參數的度數

void drawPolyline(int[], int[], int) 使用前 2個參數 int[]陣列的座標繪出多邊形,最後 1個參數 int是一共有多少點

Page 25: Ch16  繪圖與多媒體

112/04/21 25

圖形和字串的繪圖方法 -3

Page 26: Ch16  繪圖與多媒體

112/04/21 26

填滿圖形的繪圖方法 -1

• Graphics類別還提供繪出填滿圖形的相關方法,如下表所示:

方法 說明void fillRect(int, int, int, int) 使用目前色彩繪出填滿色彩的長方形,

前 2個參數 int是左上角座標(x, y),後2個分別為長方形的寬和高

void fill3DRect(int, int, int, int,boolean)

繪出 3D效果填滿的長方形,前 2個參數 int是左上角座標(x, y),後 2個分別為長方形的寬和高,最後的 boolean參數決定長方形是凸出還是凹下表面,true

是凸出void fillRoundRect(int, int, int,int, int, int)

繪出填滿的圓角長方形,前 2個參數 int

是左上角座標(x, y),接著 2個分別為長方形的寬和高,最後 2個參數 int是決定圓角弧度的水平和垂直尺寸

Page 27: Ch16  繪圖與多媒體

112/04/21 27

填滿圖形的繪圖方法 -2

void fillOval(int, int, int, int) 繪出填滿的圓形或橢圓形,圖形是位在長方形的範圍內,前 2個參數 int是左上角座標(x, y),後 2個分別為長方形的寬和高

void fillArc(int ,int, int, int, int,int)

繪出一段填滿的弧形,弧形是位在長方形的範圍內,前 2個參數 int是左上角座標(x, y),接著 2個分別為長方形的寬和高,最後 2個參數 int是從第 1個 int

的角度開始(時鐘的 3點位置是 0),到最後參數的度數

void fillPolyline(int[], int[], int) 使用前 2個參數 int[]陣列的座標繪出填滿的多邊形,最後 1個參數 int是一共有多少點

Page 28: Ch16  繪圖與多媒體

112/04/21 28

填滿圖形的繪圖方法 -3

Page 29: Ch16  繪圖與多媒體

112/04/21 29

圖片的載入與顯示 -說明• Java程式是使用 Image物件來載入圖片, Image是抽象類別,其繼承的子類別可以儲存多種格式的圖片檔案。

• 在使用上是以 Toolkit抽象類別( Abstract Window Toolkit實作的抽象類別)的方法將圖檔載入成為 Image物件。

Page 30: Ch16  繪圖與多媒體

112/04/21 30

圖片的載入與顯示 -載入• 首先使用 getDefaultToolkit()取得 Toolkit物件,如下所示:Toolkit toolkit = Toolkit.getDefaultToolkit();

• 程式碼在取得 Toolkit物件 toolkit後,使用getImage()方法載入圖檔,例如:取得JPG圖檔 sample.jpg 的 Image物件,其程式碼如下所示:Image image = toolkit.getImage("sample.jpg");

Page 31: Ch16  繪圖與多媒體

112/04/21 31

圖片的載入與顯示 -顯示

• 在 paint() 或 paintComponent()方法使用drawImage()顯示圖檔的 Image物件,如下所示:g.drawImage(image, 5, 5, this);

• 程式碼是在座標 (5, 5)顯示名為 image 的Image物件,實作 ImageObserver介面的物件是元件本身 this,因為繼承自Component類別的 Swing元件都已經實作ImageObserver介面,所以使用元件本身即可。

Page 32: Ch16  繪圖與多媒體

112/04/21 32

範例 5:讀取圖片1. import javax.swing.*;2. import java.awt.*;3. import java.awt.event.*;

4. class Ch11_15 extends JFrame5. {6. //建構子7. Ch11_15()8. {9. super("載入與顯示圖片 ");10. Container c = getContentPane();11. Toolkit toolkit = Toolkit.getDefaultToolkit();12. Image image =

toolkit.getImage("MickeyChristmas.jpg");13. ImagePanel imagePane = new

ImagePanel(image);14. c.add(imagePane);15. }

16. class ImagePanel extends JPanel17. {18. private Image image;19. //建構子20. ImagePanel(Image image)21. {22. this.image = image;23. } 24. public void paintComponent(Graphics g)25. {26. super.paintComponent(g);27. g.drawImage(image, 5, 5, this);28. }29. }

30. public static void main(String [] args)31. {32. Ch11_15 app = new Ch11_15();33. // 關閉視窗事件 , 結束程式的執行34. app.addWindowListener(new WindowAdapter()35. { public void windowClosing(WindowEvent evt)36. { System.exit(0); }37. });38. app.setSize(370,320); // 設定尺寸39. app.setVisible(true); // 顯示視窗40. }41. }

Page 33: Ch16  繪圖與多媒體

112/04/21 33

圖片的載入與顯示 -圖例

Page 34: Ch16  繪圖與多媒體

112/04/21 34

調整圖片尺寸 -圖片的放大與縮小

• drawImage()方法新增參數 width 和 height,分別是圖片的寬和高,如果設定的尺寸比原圖形小是縮小圖片,反之就是放大圖片。

boolean drawImage(Image image, int x, int y, int width, int height, ImageObserver observer)

Page 35: Ch16  繪圖與多媒體

112/04/21 35

調整圖片尺寸 -圖片的翻轉與剪裁

boolean drawImage(Image image, int x1, int y1, int x2, int y2,

int sx1, int sy1, int sx2, int sy2, ImageObserver observer)

• drawImage()方法參數的 4個座標分成 2組,其說明如下表所示:座標 說明

(x1, y1) 顯示圖片的左上角座標(x2, y2) 顯示圖片的右下角座標

(sx1,sy1) 原始圖片的左上角座標(sx2, sy2) 原始圖片的右下角座標

Page 36: Ch16  繪圖與多媒體

112/04/21 36

調整圖片尺寸 -圖片翻轉• 首先來看翻轉圖片情況:如果 sample.gif原始圖片尺寸的寬是 width,高是 height,原始圖片的左上角座標是 (0, 0),右下角座標為 (width, height),翻轉操作如下:–原尺寸上下翻轉:原始圖片座標分別為 (0,

height) 和 (width, 0),換句話說,原始圖片的左下角成為顯示圖片的左上角,而右上角成為右下角。

–原尺寸左右翻轉:原始圖片座標分別為 (width, 0) 和 (0, height),換句話說,原始圖片的右上角成為顯示圖片的左上角,而左下角成為右下角。

Page 37: Ch16  繪圖與多媒體

112/04/21 37

調整圖片尺寸 -圖片的剪裁

• 翻轉與剪裁圖片是使用第 2組座標,如果第 2組座標的尺寸只有部分的圖片,就會剪裁圖片。

Page 38: Ch16  繪圖與多媒體

112/04/21 38

範例 6:圖片放大 ,縮小 , 旋轉1. class ImagePanel extends JPanel2. {3. private Image image;4. //建構子5. ImagePanel(Image image)6. {7. setPreferredSize(new Dimension(900, 620));8. this.image = image;9. } 10. public void paintComponent(Graphics g)11. {12. int x, y, width, height;13. width = image.getWidth(this);14. height = image.getHeight(this);15. super.paintComponent(g);16. x = 0;17. y = 5;18. g.drawImage(image, x, y, this);19.

20. //縮小 1/221. x += width; // 設定第二張圖的起始位置22. g.drawImage(image, x, y, width/2, height/2, this);

23. //上下旋轉24. x += width/2;25. g.drawImage(image, x, y, x+width, y+height, 0,

height, width, 0, this);

26. //左右旋轉27. x = 0;28. y += height +5;29. g.drawImage(image, x, y, x+height/2, y+width/2,

width, 0,0,height, this);

30. //放大並剪裁 (取原圖的 1/4並放大到原圖大小 )31. x += height/2;32. g.drawImage(image, x, y, x+width, y+height,

0,0,width/2, height/2, this);

33. }34. }

Page 39: Ch16  繪圖與多媒體

112/04/21 39

動畫效果• 動畫效果是使用卡通片的製作原理,快速顯示一張張靜態圖片,因為每張圖片擁有少許改變。例如:位移或尺寸,或定時在不同位置繪出圖形,在人類視覺殘留的情況下,就會產生動畫效果。

Page 40: Ch16  繪圖與多媒體

112/04/21 40

Timer類別的時間控制 -說明• 在 Java程式建立動畫效果是使用 Timer計時器類別控制繪圖或圖片顯示, Timer類別可以在間隔時間自動產生事件,以便指定傾聽者物件進行處理。 Timer類別的建構子,如下表所示:

建構子 說明Timer(int,

ActionListener)建立 Timer物件,參數 int是間隔時間,以毫秒為單位,也就是在每一個間隔時間到時,產生事件

由第 2個參數的傾聽者物件來處理

Page 41: Ch16  繪圖與多媒體

112/04/21 41

Timer類別的時間控制 -使用

• Timer類別的使用十分的簡單,只需先建立好 Timer物件,如下所示:Timer timer = new Timer(300, this);

• 上述程式碼建立 Timer物件且設定 300毫秒間隔時間產生事件,傾聽者物件是本身,接著就可以呼叫下表 Timer類別的方法啟動、重新啟動和停止計時器。

Page 42: Ch16  繪圖與多媒體

112/04/21 42

Timer類別的時間控制 -方法 1

• 呼叫下表 Timer類別的方法啟動、重新啟動和停止計時器,如下表所示:

方法 說明void start(0 啟動計時器

void restart() 在取消所有擱置的事件後,重新啟動計時器void stop() 停止計時器

boolean isRunning() 檢查計時器是否在執行中,傳回值 true為是,false為否

Page 43: Ch16  繪圖與多媒體

112/04/21 43

Timer類別的時間控制 -方法 2

• Timer類別的其它相關方法,如下表所示:

方法 說明void setDelay(int) 設定計時器的間隔時間,以毫秒為單位

int getDelay() 取得計時器的間隔時間void setInitialDelay() 設定在產生第 1次事件前的等待時間,以毫秒

為單位,預設為間隔時間int getInitilaDealy() 取得產生第 1次事件前的等待時間

voidsetRepeats(boolean)

設定計時器是否自動重複計時,參數 boolean

為 true表示重複,false為不重複boolean isRepeats() 檢查計時器是否重複執行計時,傳回值 true為

是,false為否

Page 44: Ch16  繪圖與多媒體

112/04/21 44

圖片移動的動畫效果• 在 Java程式只需使用 Timer類別配合圖片載入與顯示,就可以建立圖片移動橫跨螢幕的動畫效果。

Page 45: Ch16  繪圖與多媒體

112/04/21 45

範例 7:動畫1. import javax.swing.*;2. import java.awt.*;3. import java.awt.event.*;4. // 繼承 JFrame類別 , 實作 ActionListener介面5. public class Ch11_08 extends JFrame6. implements ActionListener7. { private int offset = -10;8. private Image im;

9. private Timer timer;10. private AnimationPane animationPane;11. // 建構子12. public Ch11_08()13. { super("動畫功能的顯示範例 ");14. int delay = 100;15. timer = new Timer(delay, this);16. timer.setInitialDelay(0);17. Container c = getContentPane();18. c.setLayout(new FlowLayout()); 19. c.setBackground(Color.gray);20. Toolkit toolkit = Toolkit.getDefaultToolkit();21. im = toolkit.getImage("023.gif");22. animationPane = new AnimationPane(im); 23. c.add(animationPane);24. timer.start(); 25. }26. app.setSize(300, 150); // 設定尺寸27. app.setVisible(true); // 顯示視窗28. }29. }

30. // 顯示動畫的 JPanel31. class AnimationPane extends JPanel32. { Image image;33. // 建構子34. public AnimationPane(Image image)35. { setPreferredSize(new Dimension(250, 100));36. setBackground(Color.lightGray);37. this.image = image;38. }39. public void paintComponent(Graphics g)40. { super.paintComponent(g);41. int width = getWidth();42. int height = getHeight();43. // 計算圖片的尺寸44. int imgWidth = image.getWidth(this);45. int imgHeight = image.getHeight(this);46. g.drawImage(image,((offset*5)%(imgWidth+width))47. - imgWidth, (height-imgHeight)/2, this);48. }49. }50. // 實作事件處理方法51. public void actionPerformed(ActionEvent evt)52. { offset++;53. animationPane.repaint(); // 重繪54. }55. // 主程式56. public static void main(String[] args) 57. { // 建立 Swing應用程式58. Ch11_08 app = new Ch11_08();59. // 關閉視窗事件 , 結束程式的執行60. app.addWindowListener(new WindowAdapter()61. { public void windowClosing(WindowEvent evt)62. { System.exit(0); }63. });

Page 46: Ch16  繪圖與多媒體

112/04/21 46

範例 8:動畫 (會更換圖片 )1. import java.awt.*;2. import java.applet.*;

3. public class Ch11_09 extends Applet4. implements Runnable5. {6. Thread fly;7. int x, y, dx, dy, flag, num, i;8. Image [] Img;

9. public void init()10. {11. x = getWidth();12. y = 50;13. dx = -5;14. dy = 0;15. Img = new Image[4];16. num = 1;17. Img[0] = getImage(getDocumentBase(), "013.gif");18. Img[1] = getImage(getDocumentBase(), "023.gif");19. Img[2] = getImage(getDocumentBase(), "024.gif");20. Img[3] = getImage(getDocumentBase(), "001.gif");21. }

22. public void start()23. {24. fly = new Thread(this);25. fly.start();26. }27. 28. public void run()29. {30. while(true)31. {32. x = x + dx;33. y = y + dy;34. flag = num % 4;35. repaint();36. num = num + 1;37. 38. if(x<0) 39. x = getWidth();40. 41. try42. { Thread.sleep(1500); }43. catch (InterruptedException e) {}44. }45. }

46. public void paint(Graphics g)47. {48. g.drawImage(Img[flag], x, y, x+10, y+25, this);49. }50. }

Page 47: Ch16  繪圖與多媒體

112/04/21 47

Java Applet的圖片載入 -Applet• 在 Java Applet程式載入和顯示圖片是使用

getImage()方法將圖片載入成為 Image物件,例如:建立 URL物件來載入圖片,如下所示:

Image image = getImage( new

URL("http://www.company.com/sample.gif"));• 使用 getDocumentBase() 或 getCodeBase()方法取得檔案的 URL位置,如下圖所示:

Image image =

getImage(getDocumentBase(),"sample.gif");

Page 48: Ch16  繪圖與多媒體

112/04/21 48

Java Applet的圖片載入 -JApplet

• Java Applet繼承自 JApplet可以使用 Swing 的ImageIcon物件來載入和顯示圖片。例如:使用ImageIcon載入 Baby.jpg圖檔的程式碼,如下所示:

ImageIcon image1 = new ImageIcon("Baby.jpg");• 在載入圖片成為 ImageIcon物件後,就可以使用

paintIcon()方法顯示圖片,如下所示:image1.paintIcon(this, g, 5, 5);

Page 49: Ch16  繪圖與多媒體

112/04/21 49

音樂的播放 -說明• 在 Java Applet不只可以顯示圖片,還可以播放音樂檔案,目前支援的音樂檔案格式有 au 、 aiff 、 wav 、 mid 和 rmf。

Page 50: Ch16  繪圖與多媒體

112/04/21 50

音樂的播放 -載入• 在 Java API 的 java.applet.*套件的 Applet類別提供 getAudioClip()方法建立AudioClip物件載入音樂檔案,如下所示:

AudioClip audio = getAudioClip(getDocumentBase(),"Microsoft.wav");

• 程式碼建立 AudioClip物件,參數為 URL物件和音樂檔案名稱。

Page 51: Ch16  繪圖與多媒體

112/04/21 51

音樂的播放 -播放• 在建立好 AudioClip物件後,就可以使用

AudioClip介面的 3個方法控制音樂的播放,如下表所示:

方法 說明void play() 播放音樂void loop() 重複播放音樂void stop() 停止播放音樂

Page 52: Ch16  繪圖與多媒體

112/04/21 52

範例 8:播放音樂 (使用 Applet)1. import java.awt.*;2. import java.awt.event.*;3. import javax.swing.*;4. import java.applet.*;5. // 繼承 JApplet類別 , 實作

ActionListener介面6. public class Ch11_07 extends JApplet7. implements ActionListener8. { private AudioClip audio; 9. private JButton play, loop, stop;10. // 初始方法11. public void init()12. { // 取得參數13. String file = getParameter("FILE");14. Container c = getContentPane(); 15. c.setBackground(Color.gray);16. c.setLayout(new

FlowLayout(FlowLayout.CENTER));17. audio =

getAudioClip(getDocumentBase(), file);

18. play = new JButton("播放 ");19. play.addActionListener(this);20. c.add(play);21. loop = new JButton("循環播放 ");22. loop.addActionListener(this);23. c.add(loop);24. stop = new JButton("停止 ");25. stop.addActionListener(this);26. c.add(stop);27. }28. // 實作事件處理方法29. public void

actionPerformed(ActionEvent evt)30. { if (evt.getSource()==play)

audio.play();31. else if (evt.getSource()==loop)

audio.loop();32. else if (evt.getSource()==stop)

audio.stop();33. }34. }

Page 53: Ch16  繪圖與多媒體

112/04/21 53

範例 8:播放音樂 (使用 Applet)-續1. <html>2. <head><title>Ch11_07.htm</title></head>3. <body>4. <applet code="Ch11_07.class" width=350

height=50>5. <param name="File"

value="FIR_YueYaWan_F.mid">6. </applet>7. </body>8. </html>

Page 54: Ch16  繪圖與多媒體

112/04/21 54

範例 9:播放音樂 (使用 Sound)1. import java.io.*;2. import javax.sound.sampled.*;3. public class Ch11_07_024. {5. public static void main(String args [])6. {7. try8. {9. System.out.println("播放聲音檔案 : " + "jay1.wav");10. File sf = new File("jay1.wav");11. //取得聲音輸入串流12. AudioInputStream astr =

AudioSystem.getAudioInputStream(sf);13. //取得聲音形式14. AudioFormat afmt = astr.getFormat();15. //建立訊號線資訊物件16. DataLine.Info inf = new

DataLine.Info(SourceDataLine.class, afmt);17. //取得符合指定訊號線資訊的訊號線18. SourceDataLine l = (SourceDataLine)

AudioSystem.getLine(inf);

1. //以指定形式開啟訊號線2. l.open(afmt);3. //開始訊號線的讀寫4. l.start();5. //讀寫緩寫區6. byte [] buf = new byte[65536];7. //從聲音串流讀入資料寫入混音器8. for(int n = 0; (n=astr.read(buf, 0,

buf.length))>0; )9. {10. l.write(buf, 0, n);11. }12. //清掉混音器內的資料13. l.drain();14. //關閉15. l.close();16. } catch (Exception e)17. {18. e.printStackTrace();19. }20. 21. System.exit(0);22. }23. }

Page 55: Ch16  繪圖與多媒體

112/04/21 55

範例 10:滑鼠控制圖像移動1. import java.awt.*;2. import java.applet.*;

3. public class Ch11_21 extends Applet 4. implements Runnable5. {6. Thread flag;7. int x, y, dx, dy;8. Image Img;9. Point clickPoint;10. String message = "";

11. public void init()12. {13. x = y = 50;14. dx = 5;15. dy = 0;16. Img = getImage(getDocumentBase(),

"010.gif");17. }

18. public boolean mouseDown(Event evt, int mx, int my)19. {20. if((mx >= 400) && (mx <= 410) && (my >= 400) && (my <= 410))21. {22. dx = 0;23. dy = -5;24. }25. if((mx >= 400) && (mx <= 410) && (my >= 440) && (my <= 450))26. {27. dx = 0;28. dy = 5;29. }30. if((mx >= 380) && (mx <= 390) && (my >= 420) && (my <= 430))31. {32. dx = -5;33. dy = 0;34. }35. if((mx >= 420) && (mx <= 430) && (my >= 420) && (my <= 430))36. {37. dx = 5;38. dy = 0;39. }40. clickPoint = new Point(mx, my);41. message = "Mouse_click_Position: )" + mx + ", " + my + " )";42. repaint();43. return true;44. }

Page 56: Ch16  繪圖與多媒體

112/04/21 56

範例 10:滑鼠控制圖像移動(續)45. public void start()46. {47. flag = new Thread(this);48. flag.start();49. }

50. public void run()51. {52. while(true)53. {54. x = x + dx;55. y = y + dy;56. repaint();57. 58. if ( x <= 0)59. dx = 5;60. else if( x+70 >= getWidth())61. dx = -5;62. else if( y+70 >= getHeight()) 63. dy = -5;

64. try65. { Thread.sleep(250); }66. catch(InterruptedException e) {}67. }68. }

69. public void paint(Graphics g)70. {71. g.drawString(message, 5, 15);72. g.drawRect(400, 400, 10, 10);73. g.drawRect(400, 440, 10, 10);74. g.drawRect(380, 420, 10, 10);75. g.drawRect(420, 420, 10, 10);

76. g.drawImage(Img, x, y, this);77. }78. }

Page 57: Ch16  繪圖與多媒體

112/04/21 57

範例 11:方向鍵控制圖像移動1. import java.awt.*;2. import java.applet.*;

3. public class Ch11_22 extends Applet 4. implements Runnable5. {6. Thread flag;7. int x, y, dx, dy;8. Image Img;

9. public void init()10. {11. x = y = 50;12. dx = 5;13. dy = 0;14. Img = getImage(getDocumentBase(), "010.gif");15. }

16. public boolean keyDown(Event evt, int key)17. {18. switch (key)19. {20. case Event.UP:21. dx = 0;22. dy = -5;23. break;24. case Event.DOWN:25. dx = 0;26. dy = 5;27. break;28. case Event.LEFT:29. dx = -5;30. dy = 0;31. break;32. case Event.RIGHT:33. dx = 5;34. dy = 0;35. }36. return true;37. }

38. public void start()39. {40. flag = new Thread(this);41. flag.start();42. }

Page 58: Ch16  繪圖與多媒體

112/04/21 58

範例 11:方向鍵控制圖像移動(續)

43. public void run()44. {45. while(true)46. {47. x = x + dx;48. y = y + dy;49. repaint();50. 51. if ( x <= 0)52. dx = 5;53. else if( x+70 >= getWidth())54. dx = -5;55. else if( y+70 >= getHeight()) 56. dy = -5;

57. try58. { Thread.sleep(250); }59. catch(InterruptedException e) {}60. }61. }

62. public void paint(Graphics g)63. {64. g.drawImage(Img, x, y, this);65. }66. }

Page 59: Ch16  繪圖與多媒體

112/04/21 59

研究:用球擊中靶塊• import java.awt.*;• import java.lang.*;• import java.applet.*;

• public class BlockHit extends Applet implements Runnable• {• int fieldx1 = 0;• int fieldy1 = 0;• int fieldx2 = 256;• int fieldy2 = 306;

• int block_xnum = 10;• int block_ynum = 8;• int block_width = 15;• int block_height = 5;• int block_left_board = 6;• int block_up_board = 46;• int block_lower_board = 116;

• int pad_width = 20;

• Graphics g;• Thread theBall;• int blockState[][] = new int[block_xnum][block_ynum];• int padx;• int ballX, ballY;• int ballDX,ballDY;• int speed;• int eraseCount;• int padHitCount;• int score;• int left;• boolean onGame;• boolean onFireBall;• Panel pControl;• Label lScore, lLeft;• Button bControl;• int threadProcessing;

• public void init()• {• setLayout(new BorderLayout());• setBackground(Color.green);• g = getGraphics();

• pControl = new Panel();• pControl.setBackground(Color.gray);• pControl.setLayout(new FlowLayout());• bControl = new Button(" START ");• lScore = new Label("SCORE:0 ");• lLeft = new Label("LEFT:5");• pControl.add(bControl);• pControl.add(lScore);• pControl.add(lLeft);

• add("South", pControl);• }

• public void start()• {• gameInit();• onGame = false;• onFireBall = false;• }

Page 60: Ch16  繪圖與多媒體

112/04/21 60

• void gameInit()• {

• for (int x = 0 ; x < block_xnum ; x++)• for (int y = 0 ; y < block_ynum ; y++)• blockState[x][y] = 1;

• padx = fieldx2 / 2;• • score = 0;• addScore(0);• left = 5;• subLeft(0);• eraseCount = 0;• bControl.setLabel(" START ");

• threadProcessing = 0;• repaint();• }

• public void paint(Graphics g)• {• g.drawRect(fieldx1, fieldy1, fieldx2, fieldy2);

• g.setColor(Color.blue);• for (int y = 0 ; y < block_ynum ; y++)• {• for (int x = 0 ; x < block_xnum ; x++)• {• if (blockState[x][y] == 1)• g.fillRect(block_left_board + x * (block_width + 10) ,• block_up_board + y * (block_height +5) ,• block_width, block_height);• }• }• }•

• public void remakeBlock()• {• g.setColor(Color.blue);• for (int x = 0 ; x < block_xnum ; x++)• for (int y = 0 ; y < block_ynum ; y++)• {• blockState[x][y] = 1;• g.fillRect(block_left_board + x * (block_width + 10) ,• block_up_board + y * (block_height +5) ,• block_width, block_height);• }• }

• public boolean action(Event e, Object o)• {• if (e.target instanceof Button)• {• if (" START " .equals(o))• {• if (onGame == false)• {• gameInit();• bControl.setLabel("STOP");• onGame = true;• }• }• else if ("STOP" .equals(o))• {• stop();• bControl.setLabel(" START ");• onGame = false;• onFireBall = false;• }• return true;• }• return false;• }

Page 61: Ch16  繪圖與多媒體

112/04/21 61

• public boolean mouseDown(java.awt.Event e, int x, int y)• {• if (onGame == true)• {• if (onFireBall == false)• {• ballX = (padx / 10) * 10 + 1;• if (ballX > block_xnum*(block_width+10)-5)• ballX = block_xnum*(block_width+10)-5;• else if (ballX < block_left_board)• ballX = block_left_board;

• if (padx < fieldx2 / 2)• ballDX = -5;• else ballDX = 5;

• ballY = fieldy2 - 25;• ballDY = -10;

• speed = 150;• padHitCount = 0;• subLeft(1);• threadProcessing = 0;• onFireBall = true;

• if (theBall != null)• {• theBall = null;• }• if (theBall == null)• {• theBall = new Thread(this);• theBall.start();• }• }• }• return true;• }

• •

• public boolean mouseMove(java.awt.Event e, int x, int y)• {• padx = x - 7;• if (padx < 1) padx = 1;• if (padx > fieldx2 - pad_width)• padx = fieldx2 - pad_width;

• while (threadProcessing == 1) {}

• g.setColor(Color.green); • g.fillRect(1, (fieldy2 - 20), (fieldx2-1) , 5);• g.setColor(Color.black); • g.fillRect(padx, (fieldy2 - 20), pad_width , 5);• g.setColor(Color.green);

• return true;• }

• public void stop()• {• if (theBall != null)• {• theBall.stop();• theBall = null;• }• }

Page 62: Ch16  繪圖與多媒體

112/04/21 62

• public void run()• {• int ballPX,ballPY;

• while(true)• {• ballPX = ballX;• ballPY = ballY;• • ballX = ballX + ballDX;• ballY = ballY + ballDY;

• if ((ballY == (fieldy2 - 25)) && (ballX >= padx - 5) &&• (ballX <= padx + pad_width))• ballDY = -ballDY;

• if ((ballX >= (fieldx2-5)) || (ballX <= 1))• ballDX = -ballDX;• • if (ballY <= 1)• ballDY = -ballDY;

• if (ballY >= fieldy2-10)• {• if (left == 0)• {• onGame = false;• bControl.setLabel(" START ");• }• • g.setColor(Color.green); • g.fillRect(ballPX, ballPY, 5 , 5);• onFireBall = false;• theBall.stop();• }

• if (ballDY > 0) • {• if ((ballY >= block_up_board - 5) && (ballY <= block_lower_board -

5))• {• int blockX = ballX / 25;• if ((ballX - blockX * 25) >= 5)• {• int blockY = (ballY - (block_up_board - 5)) / 10;• if (blockState[blockX][blockY] == 1)• {• blockState[blockX][blockY] = 0;• g.setColor(Color.green); • g.fillRect(block_left_board + blockX * (block_width + 10) ,• block_up_board + blockY * (block_height +5),• block_width, block_height);• ballDY = -ballDY;• eraseCount = eraseCount + 1;• addScore(1);• }• }• }• }• else • {• if ((ballY >= block_up_board + 5) && (ballY <= block_lower_board

+ 5))•

Page 63: Ch16  繪圖與多媒體

112/04/21 63

•      {• int blockX = ballX / 25;• if ((ballX - blockX * 25) >= 5)• {• int blockY = (ballY - (block_up_board + 5)) / 10;• if (blockState[blockX][blockY] == 1)• {• blockState[blockX][blockY] = 0;• g.setColor(Color.green); • g.fillRect(block_left_board + blockX * (block_width + 10) ,• block_up_board + blockY * (block_height +5),• block_width, block_height);• ballDY = -ballDY;• eraseCount = eraseCount + 1;• addScore(1);• }• }• }• }• • threadProcessing = 1;• g.setColor(Color.green); • g.fillRect(ballPX, ballPY, 5 , 5);• g.setColor(Color.red); • g.fillRect(ballX, ballY, 5 , 5);• g.setColor(Color.green); • threadProcessing = 0;• • if (eraseCount == 80)• {• remakeBlock();• eraseCount = 0;• }• •

•     try• {• Thread.sleep(speed);• }• catch(InterruptedException e)• {• System.out.println("Catch Interrupt Exception");• }• }• }

• void addScore(int delta)• {• String str;

• score = score + delta;• str = "SCORE:" + String.valueOf(score);• lScore.setText(str);• }

• void subLeft(int delta)• {• String str;

• left = left - delta;• str = "LEFT:" + String.valueOf(left);• lLeft.setText(str);• }• }