Java—事件和多線程機制

一  事件java

1.1 事件源      多線程

圖形用戶界面上每一個可能產生事件的組件稱爲事件源。app

1.2 事件監聽者ide

Java系統中註冊的用於接收特殊事件的類。不一樣的事件對應着不一樣的監聽者,要想事件被監聽者監聽並處理,則需先將事件源註冊到監聽者。函數

1.3 事件處理流程佈局

事件源觸發事件並將事件做爲一個參數傳遞給監聽者,監聽者實現某個接口中的抽象方法,從而實現對事件的處理。Java的事件處理機制是一個委託事件模型。測試

事件源註冊的方法以下:字體

public void addActionListener(ActionListener l)動畫

添加特定的動做,監聽接收來自事件源的動做事件,若是l爲空,不會產生任何動做。this

監聽者實現的接口爲ActionListener接口,接口ActionListener來自包java.awt.event。

在此接口中只有一個方法:

public void actionPerformed(ActionEvent e)

當事件對象e發生時,調用此方法。監聽者就須要實現這個方法。

1.4 動做事件

ActionEvent包含一個事件,該事件爲執行動做事件ACTION_PERFORMED。觸發這個事件的動做爲:

(1) 點擊按鈕。

(2) 雙擊列表中的選項。

(3) 選擇菜單項。

(4) 在文本框中輸入回車。

經常使用方法以下:

public String getActionCommand()                            返回引起某個事件的命令按鈕的名字,若是名字爲空,那麼返回標籤值。

public void setActionCommand(String command)        設置引起事件的按鈕的名字,默認設置爲按鈕的標籤。

例:測試動做事件

 1 package test;
 2 
 3 import java.awt.*;
 4 import java.awt.event.*;
 5 import java.applet.*;
 6 public class UseButton extends Applet implements ActionListener{
 7         /**
 8      * 
 9      */
10     private static final long serialVersionUID = 1L;
11     
12         String str = new String();
13         Button b1; //聲明按鈕對象;
14         Button b2;
15         Color c;
16         public void init()
17         {
18              b1 = new Button("按鈕對象1");
19              b2 = new Button("按鈕對象2");
20              //添加事件監聽者
21              b1.addActionListener(this);
22              b1.setBackground(Color.yellow);
23              b2.addActionListener(this);
24              this.add(b1);
25              this.add(b2);
26 
27         }
28         public void start()
29         {
30             str = b1.getLabel();
31             //repaint();
32         }
33         public void paint(Graphics g)
34         {
35             g.setColor(c);
36             g.drawString("引起事件的對象的標籤:" + str, 80,60);
37         }
38         //實現接口中的方法,響應動做事件
39         public void actionPerformed(ActionEvent e)
40         {
41             String arg = e.getActionCommand();
42             if(arg == "按鈕對象1")
43             {
44                 c = Color.red;
45                 str = "按鈕對象1";
46             }
47             else if(arg == "按鈕對象2")
48             {
49                 c = Color.green;
50                 str = "按鈕對象2";
51             }
52             repaint();
53         }
54 }
View Code

點擊按鈕對象1 ,點擊按鈕對象2

輸出結果:

     

1.5 文本事件(TextEvent)

文本事件即表明文本區域中文本變化的事件TEXT_VALUE_CHANGED,在文本區域中改變文本內容。

public void addTextListener(TextListener l)                     添加特定的文本事件,監聽者接收來自文本對象的文本事件。若是l爲空,那麼不會拋出任何異常,並且也不會完成任何動做。

public interface TextListener extends EventListener         用於接收文本事件的監聽者接口。當對象的文本發生變化時,調用監聽者對象的方法。

接口中的方法爲:

public void textValueChanged(TextEvent e)                    當文本發生改變時調用。

public Object getSource()                                             發生事件的對象,從EventObject繼承來的方法。

例:測試文本事件

 1 package test;
 2 
 3 import java.awt.*;
 4 import java.awt.event.*;
 5 import java.applet.Applet;
 6 public class UseTextEvent extends Applet implements ActionListener, TextListener{
 7     /**
 8          * @ YMM 2016/05/09
 9          */
10     private static final long serialVersionUID = 1L;
11     TextField tOld;
12     TextArea tNew;
13     Panel p;
14     public void init()
15     {
16          tOld = new TextField(25);         
17          tNew = new TextArea("",8,25,TextArea.SCROLLBARS_NONE);;
18          //添加事件監聽者
19          tOld.addActionListener(this);
20          tOld.addTextListener(this);
21          //設置界面
22          p = new Panel(new BorderLayout());
23          
24          p.add(tOld,BorderLayout.NORTH);
25          p.add(tNew,BorderLayout.SOUTH);
26         
27          add(p);
28     }
29     //響應文本事件
30     public void textValueChanged(TextEvent e)
31     {
32         if(e.getSource() == tOld)
33             tNew.setText(tOld.getText());    
34     }
35         //響應動做事件
36         public void actionPerformed(ActionEvent e)
37         {
38             if(e.getSource() == tOld)
39                 tNew.setText("");
40         }
41     };
View Code

1.6  選擇事件(ItemEvent)

選擇事件中包含以事件爲表明的選擇項,選中狀態發生變化的事件ITEM_STATE_ CHANGED。引起的動做爲:

(1) 改變列表類List對象選項的選中或不選中狀態。

(2) 改變下拉列表類Choice對象選項的選中或不選中狀態。

(3) 改變複選按鈕類Checkbox對象的選中或不選中狀態。

事件源對象註冊的方法以下:

public void addItemListener(ItemListener l)                添加特定的項監聽者,接收對象的選擇項發生變化的事件。

public ItemSelectable getItemSelectable()                   ItemEvent事件的方法,返回產生事件的事件源對象。

public interface ItemListener extends EventListener     接收選項事件的監聽者接口。當選項中事件發生時,調用監聽對象的itemStateChanged方法。

public void itemStateChanged(ItemEvent e)                當用戶選中一項或未選中一項時,調用這個方法。

 1 package test;
 2 import java.awt.*;
 3 import java.awt.event.*;
 4 import java.applet.*;
 5 
 6 
 7 public class UseItemEvent extends Applet implements ItemListener{
 8     /**
 9      *  2016/05/09 @author jftt
10      */
11     private static final long serialVersionUID = 1L;
12     Checkbox cDisp;   //複選按鈕
13     Button btnDisp;   //
14     Choice cFont;      //下拉列表
15     public void init()
16     {
17          cDisp = new Checkbox("紅色");
18          btnDisp = new Button("顏色顯示");
19          //setLayout(null); 
20          btnDisp.setSize(120,120);
21          cFont = new Choice();
22          cFont.add("10");
23          cFont.add("12");
24          cFont.add("14");
25          //添加事件
26          cDisp.addItemListener(this);
27              cFont.addItemListener(this);
28              add(cDisp);
29              add(cFont);
30              add(btnDisp);
31         }
32         //接口事件
33         public void itemStateChanged(ItemEvent e)
34         {
35             Checkbox temp;
36             Choice temp2;
37             Font oldF;
38             //複選框
39             if(e.getItemSelectable() instanceof Checkbox)
40             {
41                 temp = (Checkbox)(e.getItemSelectable());    
42                 //選中爲紅色,不然爲藍色
43                     if(temp.getState())
44                         btnDisp.setBackground(Color.red);
45                     else
46                         btnDisp.setBackground(Color.yellow);
47             }
48                 //組合框
49                 if(e.getItemSelectable() instanceof Choice)
50                 {
51                     oldF = btnDisp.getFont();
52                     temp2 = (Choice)(e.getItemSelectable());
53                     String s = temp2.getSelectedItem();
54                     String s1=oldF.getName();
55                     int s2=oldF.getStyle();
56                     //設置字體
57                     btnDisp.setFont(new Font(s1,s2,Integer.parseInt(s)));// 字體,樣式(粗體,斜體等),字號
58                 }
59         }                
60 
61 }
View Code

1.7  調整事件(AdjustmentEvent)

調整事件包含一個事件,即ADJUSTMENT_VALUE_CHANGED事件,當操縱滾動條改變其滑塊位置時引起動做。AjustEvent的方法以下:

public Adjustable getAdjustable()                                               返回引起事件的對象。

public int getValue()                                                                  返回調整事件中的當前值。

public void addAdjustmentListener(AdjustmentListener l)              添加調整監聽者來接收來自對象的AdjustmentEvent實例。

public interface AdjustmentListener extends EventListener            接收調整事件的監聽接口,有一個方法:

public void adjustmentValueChanged(AdjustmentEvent e)             可在調整改變時調用這個值。

例:測試調整事件。設置一個水平滾動條,取值爲1~36,隨着滑塊的變化,滾動條的值將顯示在文本區域中,而且字體大小也會跟隨變化

 1 package test;
 2 import java.awt.*;
 3 import java.awt.event.*;
 4 import java.applet.*;
 5 
 6 public class UseAdjustmentEvent extends Applet implements AdjustmentListener{
 7     /**
 8      * @author YMM 2016/05/09
 9      */
10     private static final long serialVersionUID = 1L;
11     Scrollbar s;
12     TextArea txtValue;
13     Panel p;
14     public void init() {
15          s = new Scrollbar(Scrollbar.HORIZONTAL,0,1,10,36);
16          //添加監聽者
17          s.addAdjustmentListener(this);
18          txtValue = new TextArea(5,25);
19          //界面佈局
20          p = new Panel(new BorderLayout());
21          p.add(s,BorderLayout.NORTH);
22          p.add(txtValue,BorderLayout.SOUTH);
23          add(p);
24     }
25     public void adjustmentValueChanged(AdjustmentEvent e) {
26             int value;
27             Font oldF;
28             if(e.getAdjustable() == s)
29             { 
30                 //獲得滾動條的值
31                 value = e.getValue();
32                 //將值寫入文本區域
33                 txtValue.setText(new Integer(value).toString());
34                 //按照滾動條的值設置字體
35                 oldF = txtValue.getFont();
36                 txtValue.setFont(new Font(oldF.getName(),oldF.getStyle(),value));
37             }
38     }
39 }
View Code

1.8  鼠標事件(MouseEvent)

代表畫布或界面組件中發生的鼠標事件,包含按下鼠標、釋放鼠標、單擊鼠標、進入部件的地理位置的鼠標事件和退出部件的地理位置的鼠標事件,以及鼠標移動事件(鼠標移動和鼠標拖動)。

鼠標使用addMouseListener方法註冊,經過MouseListener接收鼠標事件;鼠標還可使用addMouseMotionListener方法註冊,經過MouseMotionListener監聽者監聽鼠標移動事件。

監聽者中有具體的方法分別針對上述具體的鼠標事件,系統可以自動分辨鼠標事件的類型並調用相應的方法,因此只需編碼實現相應的代碼就能夠了。

public int getButton()                                           返回哪一個按鈕發生變化。

public int getClickCount()                                      返回與這個事件相關的鼠標單擊的次數。

public Point getPoint()                                          返回同源部件相對的事件發生的x、y位置。

public int getX()                                                  返回同源部件相對的事件發生的x位置。

public int getY()                                                  返回同源部件相對的事件發生的y位置。

例:測試按鈕和畫布的鼠標事件,包括單擊、按下、進入和退出等

  1 package test;
  2 import java.awt.*;
  3 import java.awt.event.*;
  4 import java.applet.*;
  5 
  6 public class UseMouseEvent extends Applet implements MouseListener,MouseMotionListener{
  7     /**
  8      * 
  9      */
 10     private static final long serialVersionUID = 1L;
 11     Button btn;
 12     public void init()
 13     {
 14          btn = new Button("演示鼠標事件");
 15          add(btn);
 16          //給按鈕添加鼠標事件和鼠標移動事件
 17          btn.addMouseListener(this);
 18          btn.addMouseMotionListener(this);
 19          //給畫布添加鼠標事件和鼠標移動事件
 20          this.addMouseListener(this);
 21          this.addMouseMotionListener(this);
 22     }
 23     //單擊事件
 24     public void mouseClicked(MouseEvent e)
 25     {
 26         Point p = new Point();
 27         if(e.getSource() == btn)//getSource()發生事件的對象,從EventObject繼承來的方法。
 28 
 29         {
 30             if(e.getClickCount() == 1)
 31             {
 32                 btn.setLabel("單擊鼠標");
 33             }
 34             else if(e.getClickCount() == 2)
 35             {
 36                 btn.setLabel("雙擊鼠標");
 37             }
 38         }
 39         else
 40         {
 41             if(e.getClickCount() == 1)
 42             {
 43                 p = e.getPoint();
 44                 showStatus(p.x + "," + p.y + "單擊鼠標");
 45             }
 46             else if(e.getClickCount() == 2)
 47             {
 48                 p = e.getPoint();
 49                 showStatus(p.x + "," + p.y + "雙擊鼠標");
 50             }
 51          }
 52     }
 53     //進入事件
 54     public void mouseEntered(MouseEvent e)
 55     {
 56         if(e.getSource() == btn)
 57             btn.setLabel("進入Button");
 58         else
 59             showStatus("進入Applet");
 60     }
 61     public void mouseExited(MouseEvent e)
 62     {
 63         if(e.getSource() == btn)
 64             btn.setLabel("退出Button");
 65         else
 66             showStatus("退出Applet");
 67     }
 68     //按下事件
 69     public void mousePressed(MouseEvent e)
 70     {
 71         if(e.getSource() == btn)
 72             btn.setLabel("按下鼠標");
 73         else
 74             showStatus("按下鼠標");
 75         }
 76         //釋放事件
 77         public void mouseReleased(MouseEvent e)
 78         {
 79             if(e.getSource() == btn)
 80                 btn.setLabel("鬆開鼠標");
 81             else
 82                 showStatus("鬆開鼠標");
 83         }
 84         //移動事件
 85         public void mouseMoved(MouseEvent e)
 86         {
 87             if(e.getSource() == btn)
 88                   btn.setLabel("移動鼠標");
 89             else
 90                   showStatus("移動鼠標,新位置" + e.getX() + "," + e.getY());
 91             }
 92         //拖動事件
 93         public void mouseDragged(MouseEvent e)
 94         {
 95             if(e.getSource() == btn)
 96                 btn.setLabel("拖動鼠標");
 97             else
 98                 showStatus("拖動鼠標");
 99         }
100 }
View Code

1.9  鍵盤事件(KeyEvent)

鍵盤事件有三個:鍵盤按鍵按下,按鍵釋放,按鍵被敲擊。經常使用方法以下:

public char getKeyChar()                                          返回事件中鍵的字符。

public int getKeyCode()                                            返回整數鍵碼。

public static String getKeyText(int keyCode)               返回描述這個鍵碼的字符串,例如「HOME」、「F1」或者「A」等。

public interface KeyListener extends EventListener      用來接收鍵盤事件。使用方法addKeyListener註冊。

針對鍵盤的三個事件接口提供相應的方法進行處理,具體方法以下:

public void keyPressed(KeyEvent e)                          按鍵時引起事件處理。

public void keyReleased(KeyEvent e)                        釋放鍵時引起事件處理。

public void keyTyped(KeyEvent e)                            鍵入鍵時引起事件處理。

例:

 1 package test;
 2 
 3 import java.applet.Applet;
 4 import java.awt.*;
 5 import java.awt.RenderingHints.Key;
 6 import java.awt.event.ActionEvent;
 7 import java.awt.event.ActionListener;
 8 import java.awt.event.KeyEvent;
 9 import java.awt.event.KeyListener;
10 import java.awt.event.TextEvent;
11 import java.awt.event.TextListener;
12 
13 
14 public class UseKeyEvent extends Applet implements KeyListener,ActionListener, TextListener {
15     /**
16      * 
17      */
18     private static final long serialVersionUID = 1L;
19     Key key;
20     Button btn;
21     TextField txt;
22     public void init()
23     {
24          btn = new Button("演示鍵盤事件");
25          add(btn);
26 
27          btn.addKeyListener(this);
28 
29          this.addKeyListener(this);
30          txt = new TextField(25);    
31          //添加事件監聽者
32          txt.addActionListener(this);
33          txt.addTextListener(this);
34          //設置界面
35 
36          
37          add(txt,BorderLayout.NORTH);
38       
39     }
40     @Override
41     public void keyTyped(KeyEvent e) {//鍵入鍵時引起事件處理
42         // TODO 自動生成的方法存根
43         char ch = e.getKeyChar();
44         if(ch =='Y' || ch == 'y')
45             txt.setText ("贊成");
46         else if (ch == 'N' || ch == 'n')
47             txt.setText ("反對");
48         else
49             txt.setText ("無效");
50         
51     }
52     @Override
53     public void keyPressed(KeyEvent e) {
54         // TODO 自動生成的方法存根
55         btn.setLabel("按鍵時引起事件處理");
56     }
57     @Override
58     public void keyReleased(KeyEvent e) {
59         // TODO 自動生成的方法存根
60         btn.setLabel("釋放鍵時引起事件處理");
61     }
62     @Override
63     public void textValueChanged(TextEvent e) {
64         // TODO 自動生成的方法存根
65         
66     }
67     @Override
68     public void actionPerformed(ActionEvent e) {
69         // TODO 自動生成的方法存根
70         
71     }
72 }
View Code

二  多 線 程 機 制

2.1  線程簡介

        線程(thread)就是進程中的一個執行線索。Java虛擬機容許進程中同時執行多個線程。每一個線程都有一個優先級。具備較高優先級的線程先執行。

  線程是操做系統分配 CPU 時間的基本實體。每個應用程序至少有一個線程,也能夠擁有多個線程。線程是程序中的代碼流。多個線程能夠同時運行並能共享資源。

  線程與進程不一樣,每一個進程都須要操做系統爲其分配獨立的地址空間,而同一進程中的各個線程是在同一塊地址空間中工做。

        在 Java 程序中,一些動態效果(如動畫的實現、動態的字幕等)常利用多線程技術來實現。

        線程存在一個生命週期,由如下方法體現:

  (1)  start()方法:啓動一個線程。

  (2)  run()方法:定義該線程的動做。

  (3)  sleep()方法:使線程睡眠一段時間,單位爲ms。

  (4)  suspend()方法:使線程掛起。

  (5)  resume()方法:恢復掛起的線程。

  (6)  yield()方法:把線程移到隊列的尾部。

  (7)  stop()方法:結束線程生命週期並執行清理工做。

  (8)  destroy()方法:結束線程生命週期但不作清理工做。

        其中最經常使用的是方法start()、run()、sleep()、stop()。

2.2  線程類和Runnable接口

2.2.1. 創建Thread類的子類

class myThread extends Thread

{

      ...

public void start()//啓動線程

{

       ...

}

public void run()//運行線程

{

...

}

}

例:多線程實例,主函數給予調用

 1 public class MThread 
 2 {
 3      public static void main(String[] args) 
 4      {
 5     System.out.println("Hello World!");
 6     thread2 t1 = new thread2("線程實例1"); //建立線程實例
 7     t1.start(); //調用
 8     thread2 t2 = new thread2("線程實例2");
 9     t2.start();
10     thread2 t3 = new thread2("線程實例3");
11     t3.start();
12       }
13 }
14 //自定義線程類thread2
15 class thread2 extends Thread
16 {
17     Thread thread; //定義線程實例
18     String str;
19     //構造函數
20     public thread2(String str)
21     {
22         this.str = str;
23     }
24     //啓動線程
25     public void start()
26     {
27         thread = new Thread(this);
28         thread.start();
29     }
30 public void run()
31 {
32     int i = 0;
33     while(thread != null)
34     {
35         try
36         {
37             //計數到5時睡眠10秒
38             if(i == 5)
39                 sleep(10000);
40         }
41         catch(Exception e)
42         {
43     System.out.println(e.getMessage());
44         }
45         System.out.println(str);
46         i++;
47     }
48       }
49 };
View Code

2.2.2. 實現接口Runnable

        public interface Runnable

        Runnable接口能夠由任意試圖實現線程機制的類來實現。接口包含一個run方法。

        public void run()

        對象實現Runnable接口時,建立一個線程,啓動線程致使對象run方法的調用。

        實現接口Runnable進行多線程設計的方法較爲經常使用。下面給出一個例子。

例:編寫Applet,實現Runnable接口進行簡單的動畫演示:三幅圖片依次上移

 1 package test;
 2 
 3 import java.applet.Applet;
 4 import java.awt.Graphics;
 5 import java.awt.Image;
 6 import java.awt.Toolkit;
 7 
 8 import javax.print.DocFlavor.URL;
 9 
10 
11 public class UseRunnable extends Applet implements Runnable{
12     /**
13      * 
14      */
15     private static final long serialVersionUID = 1L;
16     Thread t;
17     Image imgs[];
18     int high,h1,h2,h3;
19     public void init()
20     {
21          high = getHeight()/3;
22          h1 = high;
23          h2 = high * 2;
24          h3 = high * 3;
25          imgs = new Image[3];
26          for (int i = 0; i < 3; i ++)
27          {
28              /*java.net.URL url=getDocumentBase();
29              imgs[i] = getImage(getDocumentBase(),(i+1) + ".jpg");*/
30              imgs[i]=Toolkit.getDefaultToolkit().getImage("E:\\WorkSpace\\ecplise-luna\\JavaTest\\src\\test\\"+(i+1)+".jpg "); 
31          }
32     }
33     public void start()
34     {
35         t = new Thread(this);
36         t.start();
37     }
38     public void stop()
39     {
40         t = null;
41     }
42     //實現接口的run方法,得到動畫效果
43     public void run()
44     {
45         while( t != null)
46         {
47             try
48             {
49                 Thread.sleep(100);
50                 repaint();
51                 h1 --;
52                 //上移,到頂點時睡眠
53                 if(h1 == 0)
54                 {
55                     Thread.sleep(3000);
56                     h2 = high;
57                 }
58                 //上移,到頂點時睡眠
59                 h2 --;
60                 if(h2 == 0)
61                 {
62                     Thread.sleep(3000);
63                      h3 = high;
64                     }
65                 //上移,到頂點時睡眠
66                 h3--;
67                 if(h3 == 0)
68                 {
69                     Thread.sleep(3000);
70                     h1 = high;
71                 }
72             }catch(InterruptedException e){
73                 System.out.println(e.getMessage());
74             }
75         }
76     }
77     public void paint(Graphics g)
78     {
79         //三幅圖片依次顯示
80         g.drawImage(imgs[0],0,h1,this);
81         g.drawImage(imgs[1],0,h2,this);
82         g.drawImage(imgs[2],0,h3,this);
83     }
84     public void update(Graphics g)
85     {
86         paint(g);
87     }
88 }
View Code
相關文章
相關標籤/搜索