一、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 事件。