Swing组件集合的事件处理(二)
2.2 多線程的Swing事件處理
為了提高其效率并降低其復(fù)雜性,所有的Swing組件都被設(shè)計為非線程安全的。盡管這聽起比較恐怖,他只是簡單的意味著對Swing組件的所有訪問需要由一個單一線程完成--事件分發(fā)線程。如果我們并不確定我們位于一個特定的線程中,我們可以使用public static boolean isDispatchThread()方法請求EventQueue類或是通過public static boolean isEventDispatchThread()方法請求SwingUtilities類。后者只是作為前者的代理。
通過EventQueue類的幫助,我們可以創(chuàng)建Runnable對象在事件分發(fā)線程上執(zhí)行來正確的訪問組件。如果我們需要在事件分發(fā)線程上執(zhí)行一個任務(wù),但是我們并不需要結(jié)果也不會關(guān)心任務(wù)何時完成時,我們可以使用EventQueue的public static void invokeLater(Runnable runnable)方法。如果是相反的情況,直到任務(wù)結(jié)束并返回值時我們才能繼承我們的工作,我們可以使用EventQueue的public static void invokeAndWait(Runnable runnable)方法。獲取值的代碼要由我們來完成,而并不是invokeAndWait()方法的返回值。
為了演示創(chuàng)建一個基于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 ActionListenerActionListener actionListener = new ActionListener() {public void actionPerformed(ActionEvent actionEvent) {System.out.println("I was selected.");}};// Attach listenersbutton.addActionListener(actionListener);frame.add(button, BorderLayout.SOUTH);frame.setSize(300, 100);frame.setVisible(true);}};EventQueue.invokeLater(runner);} }代碼所生成的按鈕如圖2-3所示:
?
首先,我們來看一下invokeLater()方法。他需要一個Runnable對象作為參數(shù)。我們創(chuàng)建一個Runnable對象并傳遞給invokeLater()方法。在當(dāng)前事件分發(fā)完成之后,Runnable對象就會執(zhí)行。
Runnable runnable = new Runnable() {public void run() {// Do work to be done} } EventQueue.invokeLater(runnable);如果我們希望我們的Swing GUI創(chuàng)建是線程安全的,那么我們所有的Swing代碼就應(yīng)該遵循這種模式。如果我們需要訪問命令行參數(shù),只需要在參數(shù)聲明前添加final關(guān)鍵字就可以了:public static void main(final String args[])。這看起已經(jīng)超出了一個簡單的示例,但是這可以保證我們程序的線程安全性,確保所有的Swing組件的訪問都是通過事件分發(fā)線程完成的。(然而調(diào)用repaint(),revalidate()以及invalidate()并不需要通過事件分發(fā)線程完成。)
列表2-1中另外一個需要解釋的代碼行就是
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 在默認(rèn)情況下,如果我們圖2-3中所示的容器中標(biāo)題欄上的小X,程序并不會關(guān)閉;相反,框架會不可見。將默認(rèn)的關(guān)閉操作設(shè)置為JFrame.EXIT_ON_CLOSE可以使得程序在會用戶點擊X時關(guān)閉。在第8章中我們探討JFrame類時我們會了解到更多的信息。?
2.2.1 使用SwingUtilities用于鼠標(biāo)按鈕標(biāo)識
Swing組件集合包含了一個名為SwingUtilities的工具類,這個類提供了一個通用幫助方法集合。在本書中,當(dāng)這個類的特定方法集合起來有用時,我們會間斷的遇到這個類。對于列表2-1中的按鈕示例,我們所感興趣的方法是與確定選中哪個鼠標(biāo)按鈕相關(guān)的方法。
MouseInputListener接口由七個方法組成:mouseClick(MouseEvent), mouseEntered(MouseEvent), mouseExited(MouseEvent), mousePressed(MouseEvent)以及MouseListener中的mouseRelease(MouseEvent),MouseMotionListener中的mouseDragged(MouseEvent)與mouseMove(MouseEvent)。如果我們需要確定當(dāng)事件發(fā)生時哪一個鼠標(biāo)按鈕被選中(或是釋放),我們可以檢測MouseEvent的modifiers屬性,并將其與InputEvent類中的各種掩碼設(shè)置常量進(jìn)行對比。
例如,要檢測鼠標(biāo)按下事件中是否是鼠標(biāo)中鍵被按下,我們可以在我們的鼠標(biāo)監(jiān)聽器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)現(xiàn)在我們不需要手動獲取標(biāo)識并與掩碼進(jìn)行對比,我們可以請求SwingUtilities來完這些工作,如下所示:
if (SwingUtilities.isMiddleMouseButton(mouseEvent)) {System.out.println("Middle button released."); }?
?
這可以使得我們的代碼變得更容易閱讀與維護(hù)。
列表2-2包含了一個更新的ButtonSample,在其中添加了另一個監(jiān)聽器來檢測哪一個鼠標(biāo)按鈕被按下。
/*** */ 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 stubRunnable 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.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {System.out.println("Right button is pressed");}}public void mouseReleased(MouseEvent event) {if(SwingUtilities.isLeftMouseButton(event)) {System.out.println("Left button is released");}if(SwingUtilities.isMiddleMouseButton(event)) {System.out.println("Middle button is released");}if(SwingUtilities.isRightMouseButton(event)) {System.out.println("Right button is released");}}};button.addActionListener(actionListener);button.addMouseListener(mouseListener);frame.add(button, BorderLayout.SOUTH);frame.setSize(300,100);frame.setVisible(true);}};EventQueue.invokeLater(runner);}}總結(jié)
以上是生活随笔為你收集整理的Swing组件集合的事件处理(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何使PING命令带上日期,做长久的跟踪
- 下一篇: 灰色简约三级CSS下拉菜单代码