Java—事件和多线程机制

一  事件

1.1 事件源      

图形用户界面上每个可能产生事件的组件称为事件源。

1.2 事件监听者

Java系统中注册的用于接收特殊事件的类。不同的事件对应着不同的监听者,要想事件被监听者监听并处理,则需先将事件源注册到监听者。

1.3 事件处理流程

事件源触发事件并将事件作为一个参数传递给监听者,监听者实现某个接口中的抽象方法,从而实现对事件的处理。Java的事件处理机制是一个委托事件模型。

事件源注册的方法如下:

public void addActionListener(ActionListener l)

添加特定的动作,监听接收来自事件源的动作事件,如果l为空,不会产生任何动作。

监听者实现的接口为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

 

转载于:https://www.cnblogs.com/feitiannengdou/p/5447369.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值