一、EventQueue 是什麼
EventQueue 是Java語言中一個核心的類,它實現了事件的處理機制,它是一個消息隊列,用於處理所有的 GUI 事件,包括滑鼠和鍵盤事件,它是 Java 事件監聽器模型的一部分。在 Java 編程中,事件處理機制是至關重要的,特別是在 GUI 應用程序中。
示例代碼:
import java.awt.EventQueue; import javax.swing.JFrame; public class Example extends JFrame { public Example() { initUI(); } private void initUI() { setTitle("EventQueue"); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(300, 200); setLocationRelativeTo(null); } public static void main(String[] args) { EventQueue.invokeLater(() -> { Example ex = new Example(); ex.setVisible(true); }); } }
二、EventQueue 的作用
1. 在運行期間調度和處理所有可運行事件。
當用戶與計算機交互時,操作系統將生成許多事件,例如滑鼠單擊或鍵盤輸入等。此類動作是非同步的,如果您從未使用事件和偵聽器,可能會錯過這些重要的動作。在此情況下,計算機將不會產生任何響應,您的應用程序將不會有任何操作。因此,您的應用程序應該監聽各種事件並針對它們給出響應。
2. 為後台事件處理線程提供服務。
許多應用程序需要使用到事件處理線程,例如通信程序、文件下載和上傳、其他網路應用程序等。它們可能需要不斷地定期更新參考信息或數據,這是由後台線程管理的。這些線程需要訪問與事件隊列相關的任務,為此,它們需要與事件隊列進行交互。
3. 處理從隊列中取出的事件。
在程序運行期間,它將使用 EventQueue 來獲取當前發生的所有事件。這些事件將放入隊列以等待處理。事件處理程序從事件隊列中獲取事件並執行相應的操作。
示例代碼:
import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JButton; import java.awt.event.ActionListener; public class ExampleButton extends JFrame { public ExampleButton() { initUI(); } private void initUI() { setTitle("Button Example"); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(300, 200); setLocationRelativeTo(null); JButton btn = new JButton("Click me"); btn.addActionListener((ActionListener) -> { System.out.println("Button clicked"); }); add(btn); } public static void main(String[] args) { EventQueue.invokeLater(() -> { ExampleButton ex = new ExampleButton(); ex.setVisible(true); }); } }
三、EventQueue 的使用
1. EventQueue 的基本使用方法
首先我們需要使用 invokeLater() 方法將事件放入事件隊列中,旨在確保此任務在事件分派線程上調用。如果您的程序不使用 invokeLater() 方法,可能會出現線程安全問題。比如我們使用swing組件中有線程安全問題的JOptionPane,不會阻塞我們程序的運行,但是可能會出現奇怪的問題,比如彈窗不會顯示,或者程序異常退出等。具體來說,使用 invokeLater() 方法有以下優點:
- 它在正確的線程上執行操作。
- 它確保所有任務的序列化執行。
- 它消除了線程不同步的可能性。
- 它確保了事件隊列的多線程同步執行。
示例代碼:
import java.awt.EventQueue; import javax.swing.JFrame; public class ExampleInvokeLater extends JFrame { public ExampleInvokeLater() { initUI(); } private void initUI() { setTitle("InvokeLater Example"); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(300, 200); setLocationRelativeTo(null); } public static void main(String[] args) { EventQueue.invokeLater(() -> { ExampleInvokeLater ex = new ExampleInvokeLater(); ex.setVisible(true); }); } }
2. EventQueue 判斷當前線程是否在事件分派線程中
許多 Java 應用程序使用多線程,這意味著絕大多數情況下,您需要在非事件線程中進行某些操作。此時,您需要判斷當前線程是否在事件分派線程中,如果不是,則您需要使用 invokeLater() 方法來確保任務在事件分派線程上調用。判斷當前線程是否在事件分派線程中的方法是:使用 EventQueue 的 isDispatchThread() 方法。
示例代碼:
import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JButton; import java.awt.event.ActionListener; import javax.swing.JOptionPane; public class ExampleIsDispatchThread extends JFrame { public ExampleIsDispatchThread() { initUI(); } private void initUI() { setTitle("IsDispatchThread Example"); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(300, 200); setLocationRelativeTo(null); JButton btn = new JButton("Click me"); btn.addActionListener((ActionListener) -> { if (EventQueue.isDispatchThread()) { JOptionPane.showMessageDialog(null, "Current thread is in Event Dispatch Thread"); } else { JOptionPane.showMessageDialog(null, "Current thread is NOT in Event Dispatch Thread"); } }); add(btn); } public static void main(String[] args) { EventQueue.invokeLater(() -> { ExampleIsDispatchThread ex = new ExampleIsDispatchThread(); ex.setVisible(true); }); } }
3. 如何自定義一個EventQueue
在 EventQueue 中可以自定義一個新的隊列,一般情況下,我們不需要自定義隊列,因為 Java 語言提供了一個默認的 EventQueue,但是在特定情況下,我們需要自定義一個隊列。例如,在一個多線程GUI應用中,如果您想要優化事件分派線程的性能,可以選擇自定義事件隊列。
我們可以通過繼承 java.awt.EventQueue 類並覆蓋其中的幾種方法來實現自己的 EventQueue,其中包括:
- dispatchEvent()
- postEvent()
- nextEvent()
- peekEvent()
- getMostRecentEventTime()
- setCurrentEventAndMostRecentTime()
示例代碼:
import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; public class ExampleCustomEventQueue extends EventQueue { @Override protected void dispatchEvent(AWTEvent event) { super.dispatchEvent(event); if (event instanceof ActionEvent) { ActionListener[] listeners = ((JButton)event.getSource()).getActionListeners(); for (ActionListener listener : listeners) { listener.actionPerformed((ActionEvent)event); } } } public static void main(String[] args) { EventQueue eventQueue = new ExampleCustomEventQueue(); Toolkit.getDefaultToolkit().getSystemEventQueue().push(eventQueue); JFrame frame = new JFrame(); frame.add(new JButton("Click me")).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("Button clicked"); } }); frame.pack(); frame.setVisible(true); } }
結論
EventQueue 是 Java 語言中事件處理機制的核心類,它用於處理 GUI 事件,如鍵盤和滑鼠事件等。它採用了事件監聽器模型來處理所有事件。在多線程 GUI 應用程序中,事件處理機制非常重要。通過使用 EventQueue,您可以訪問和處理事件隊列中的所有事件,確保正確和及時的處理所有 GUI 事件。
原創文章,作者:KZNLG,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/317440.html