zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Linux Context , Interrupts 和 Context Switching 说明
    zabbix监控cpu jumps
    国际时区 TimeZone ID列表
    onenote无法更新,提示无法流式传输、无法登陆等问题解答
    Laravel Lumen 数组操作
    ApiDoc 和 Swagger 接口文档
    现代 PHP 新特性系列
    php 流(Stream)
    laravel Lumen邮箱发送配置
    钉钉开发验证登录功能
  • 原文地址:https://www.cnblogs.com/feitiannengdou/p/5447369.html
Copyright © 2011-2022 走看看