一、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/n/317440.html