Chinaunix首页 | 论坛 | 博客
  • 博客访问: 891361
  • 博文数量: 96
  • 博客积分: 10681
  • 博客等级: 上将
  • 技术积分: 2449
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-16 17:52
文章分类

全部博文(96)

文章存档

2011年(30)

2009年(36)

2008年(30)

分类: Java

2011-02-23 09:03:57

2.2 多线程的Swing事件处理

为了提高其效率并降低其复杂性,所有的Swing组件都被设计为非线程安全的。尽管这听起比较恐怖,他只是简单的意味着对Swing组件的所有访问需要由一个单一线程完成--事件分发线程。如果我们并不确定我们位于一个特定的线程中,我们可以使用public static boolean isDispatchThread()方法请求EventQueue类或是通过public static boolean isEventDispatchThread()方法请求SwingUtilities类。后者只是作为前者的代理。

通过EventQueue类的帮助,我们可以创建Runnable对象在事件分发线程上执行来正确的访问组件。如果我们需要在事件分发线程上执行一个任务,但是我们并不需要结果也不会关心任务何时完成时,我们可以使用EventQueue的public static void invokeLater(Runnable runnable)方法。如果是相反的情况,直到任务结束并返回值时我们才能继承我们的工作,我们可以使用EventQueue的public static void invokeAndWait(Runnable runnable)方法。获取值的代码要由我们来完成,而并不是invokeAndWait()方法的返回值。

为了演示创建一个基于Swing程序的正确方法,列表2-1演示了一个用于可选中按钮的源代码。

  1. import javax.swing.*;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. public class ButtonSample {
  5.   public static void main(String args[]) {
  6.     Runnable runner = new Runnable() {
  7.       public void run() {
  8.         JFrame frame = new JFrame("Button Sample");
  9.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  10.         JButton button = new JButton("Select Me");
  11.         // Define ActionListener
  12.         ActionListener actionListener = new ActionListener() {
  13.           public void actionPerformed(ActionEvent actionEvent) {
  14.             System.out.println("I was selected.");
  15.           }
  16.         };
  17.         // Attach listeners
  18.         button.addActionListener(actionListener);
  19.         frame.add(button, BorderLayout.SOUTH);
  20.         frame.setSize(300, 100);
  21.         frame.setVisible(true);
  22.       }
  23.     };
  24.     EventQueue.invokeLater(runner);
  25.   }
  26. }

代码所生成的按钮如图2-3所示:

swing_2_3

首先,我们来看一下invokeLater()方法。他需要一个Runnable对象作为参数。我们创建一个Runnable对象并传递给invokeLater()方法。在当前事件分发完成之后,Runnable对象就会执行。

  1. Runnable runnable = new Runnable() {
  2.   public void run() {
  3.     // Do work to be done
  4.   }
  5. }
  6. EventQueue.invokeLater(runnable);

如果我们希望我们的Swing GUI创建是线程安全的,那么我们所有的Swing代码就应该遵循这种模式。如果我们需要访问命令行参数,只需要在参数声明前添加final关键字就可以了:public static void main(final String args[])。这看起已经超出了一个简单的示例,但是这可以保证我们程序的线程安全性,确保所有的Swing组件的访问都是通过事件分发线程完成的。(然而调用repaint(),revalidate()以及invalidate()并不需要通过事件分发线程完成。)

列表2-1中另外一个需要解释的代码行就是

  1. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
在默认情况下,如果我们图2-3中所示的容器中标题栏上的小X,程序并不会关闭;相反,框架会不可见。将默认的关闭操作设置为JFrame.EXIT_ON_CLOSE可以使得程序在会用户点击X时关闭。在第8章中我们探讨JFrame类时我们会了解到更多的信息。

2.2.1 使用SwingUtilities用于鼠标按钮标识

Swing组件集合包含了一个名为SwingUtilities的工具类,这个类提供了一个通用帮助方法集合。在本书中,当这个类的特定方法集合起来有用时,我们会间断的遇到这个类。对于列表2-1中的按钮示例,我们所感兴趣的方法是与确定选中哪个鼠标按钮相关的方法。

MouseInputListener接口由七个方法组成:mouseClick(MouseEvent), mouseEntered(MouseEvent), mouseExited(MouseEvent), mousePressed(MouseEvent)以及MouseListener中的mouseRelease(MouseEvent),MouseMotionListener中的mouseDragged(MouseEvent)与mouseMove(MouseEvent)。如果我们需要确定当事件发生时哪一个鼠标按钮被选中(或是释放),我们可以检测MouseEvent的modifiers属性,并将其与InputEvent类中的各种掩码设置常量进行对比。

例如,要检测鼠标按下事件中是否是鼠标中键被按下,我们可以在我们的鼠标监听器mousePressed()方法中使用下面的代码:

  1. public void mousePressed(MouseEvent mouseEvent) {
  2.   int modifiers = mouseEvent.getModifiers();
  3.   if ((modifiers & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {
  4.     System.out.println("Middle button pressed.");
  5.   }
  6. }

尽管这种方法可以工作得很好,然而SwingUtilities类提供三个方法可以使得这个过程更为简单:

  1. SwingUtilities.isLeftMouseButton(MouseEvent mouseEvent) 
  2. SwingUtilities.isMiddleMouseButton(MouseEvent mouseEvent) 
  3. SwingUtilities.isRightMouseButton(MouseEvent mouseEvent)

现在我们不需要手动获取标识并与掩码进行对比,我们可以请求SwingUtilities来完这些工作,如下所示:


  1. if (SwingUtilities.isMiddleMouseButton(mouseEvent)) {
  2.   System.out.println("Middle button released.");
  3. }

这可以使得我们的代码变得更容易阅读与维护。

列表2-2包含了一个更新的ButtonSample,在其中添加了另一个监听器来检测哪一个鼠标按钮被按下。

  1. /**
  2.  *
  3.  */
  4. package swingstudy.ch02;
  5.  
  6. import java.awt.BorderLayout;
  7. import java.awt.EventQueue;
  8. import java.awt.event.ActionEvent;
  9. import java.awt.event.ActionListener;
  10. import java.awt.event.InputEvent;
  11. import java.awt.event.MouseAdapter;
  12. import java.awt.event.MouseEvent;
  13. import java.awt.event.MouseListener;
  14.  
  15. import javax.swing.JButton;
  16. import javax.swing.JFrame;
  17. import javax.swing.SwingUtilities;
  18.  
  19. /**
  20.  * @author lenovo
  21.  *
  22.  */
  23. public class ButtonSample2 {
  24.  
  25.     /**
  26.      * @param args
  27.      */
  28.     public static void main(String[] args) {
  29.         // TODO Auto-generated method stub
  30.  
  31.         Runnable runner = new Runnable() {
  32.             public void run() {
  33.                 JFrame frame = new JFrame("Button Sample");
  34.                 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  35.  
  36.                 JButton button = new JButton("Select Me");
  37.  
  38.                 ActionListener actionListener = new ActionListener() {
  39.                     public void actionPerformed(ActionEvent event) {
  40.                         System.out.println("I was selected");
  41.                     }
  42.                 };
  43.  
  44.                 MouseListener mouseListener = new MouseAdapter() {
  45.                     public void mousePressed(MouseEvent event) {
  46.                         int modifiers = event.getModifiers();
  47.  
  48.                         if((modifiers & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
  49.                             System.out.println("Left button is pressed");
  50.                         }
  51.  
  52.                         if((modifiers & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {
  53.                             System.out.println("Middle button is pressed");
  54.                         }
  55.  
  56.                         if((modifiers & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
  57.                             System.out.println("Right button is pressed");
  58.                         }
  59.                     }
  60.  
  61.                     public void mouseReleased(MouseEvent event) {
  62.                         if(SwingUtilities.isLeftMouseButton(event)) {
  63.                             System.out.println("Left button is released");
  64.                         }
  65.  
  66.                         if(SwingUtilities.isMiddleMouseButton(event)) {
  67.                             System.out.println("Middle button is released");
  68.                         }
  69.  
  70.                         if(SwingUtilities.isRightMouseButton(event)) {
  71.                             System.out.println("Right button is released");
  72.                         }
  73.                     }
  74.                 };
  75.  
  76.                 button.addActionListener(actionListener);
  77.                 button.addMouseListener(mouseListener);
  78.  
  79.                 frame.add(button, BorderLayout.SOUTH);
  80.                 frame.setSize(300,100);
  81.                 frame.setVisible(true);
  82.             }
  83.         };
  84.  
  85.         EventQueue.invokeLater(runner);
  86.     }
  87.  
  88. }
阅读(1510) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~