一、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-hant/n/317440.html
微信掃一掃
支付寶掃一掃