Swing組件集合的事件處理(二) – JAVA編程語言程序開發技術文章

 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演示瞭一個用於可選中按鈕的源代碼。


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonSample {
  public static void main(String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        JFrame frame = new JFrame(“Button Sample”);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton(“Select Me”);
        // Define ActionListener
        ActionListener actionListener = new ActionListener() {
          public void actionPerformed(ActionEvent actionEvent) {
            System.out.println(“I was selected.”);
          }
        };
        // Attach listeners
        button.addActionListener(actionListener);
        frame.add(button, BorderLayout.SOUTH);
        frame.setSize(300, 100);
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runner);
  }
}代碼所生成的按鈕如圖2-3所示:


 swing_2_3


首先,我們來看一下invokeLater()方法。他需要一個Runnable對象作為參數。我們創建一個Runnable對象並傳遞給invokeLater()方法。在當前事件分發完成之後,Runnable對象就會執行。


Runnable runnable = new Runnable() {
  public void run() {
    // Do work to be done
  }
}
EventQueue.invokeLater(runnable);如果我們希望我們的Swing GUI創建是線程安全的,那麼我們所有的Swing代碼就應該遵循這種模式。如果我們需要訪問命令行參數,隻需要在參數聲明前添加final關鍵字就可以瞭:public static void main(final String args[])。這看起已經超出瞭一個簡單的示例,但是這可以保證我們程序的線程安全性,確保所有的Swing組件的訪問都是通過事件分發線程完成的。(然而調用repaint(),revalidate()以及invalidate()並不需要通過事件分發線程完成。)


列表2-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()方法中使用下面的代碼:


public void mousePressed(MouseEvent mouseEvent) {
  int modifiers = mouseEvent.getModifiers();
  if ((modifiers & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {
    System.out.println(“Middle button pressed.”);
  }
}盡管這種方法可以工作得很好,然而SwingUtilities類提供三個方法可以使得這個過程更為簡單:


SwingUtilities.isLeftMouseButton(MouseEvent mouseEvent)
SwingUtilities.isMiddleMouseButton(MouseEvent mouseEvent)
SwingUtilities.isRightMouseButton(MouseEvent mouseEvent)現在我們不需要手動獲取標識並與掩碼進行對比,我們可以請求SwingUtilities來完這些工作,如下所示:


if (SwingUtilities.isMiddleMouseButton(mouseEvent)) {
  System.out.println(“Middle button released.”);
}這可以使得我們的代碼變得更容易閱讀與維護。


列表2-2包含瞭一個更新的ButtonSample,在其中添加瞭另一個監聽器來檢測哪一個鼠標按鈕被按下。


/**
 *
 */
package swingstudy.ch02;
 
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
 
/**
 * @author lenovo
 *
 */
public class ButtonSample2 {
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
 
  Runnable runner = new Runnable() {
   public void run() {
    JFrame frame = new JFrame(“Button Sample”);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
    JButton button =  new JButton(“Select Me”);
 
    ActionListener actionListener = new ActionListener() {
     public void actionPerformed(ActionEvent event) {
      System.out.println(“I was selected”);
     }
    };
 
    MouseListener mouseListener = new MouseAdapter() {
     public void mousePressed(MouseEvent event) {
      int modifiers = event.getModifiers();
 
      if((modifiers & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
       System.out.println(“Left button is pressed”);
      }
 
      if((modifiers & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {
       System.out.println(“Middle button is pressed”);
      }
 
      if((modifiers & InputEvent.BU

發佈留言