`
daniel.wuz
  • 浏览: 103314 次
  • 性别: Icon_minigender_1
  • 来自: 纽约
最近访客 更多访客>>
社区版块
存档分类

[转帖]Swing中的EventQueue

阅读更多

最近在看多线程的东西,Swing中的EventQueue负责所有AWTEvent(以及其子类)的分发,以后如果要定义自己的ProgressBar可能会用到,先记下来。

EventQueue简单工作原理

简单来讲,在EventQueue中有一个dispatchThread,这是一个线程类,负责事件的分发,当Queue中有事件的时候,它会摘取前面的事件并分发给相应的对象进行处理,等处理完之后再获取下一个,当Queue中没有事件的时候,线程等待。<o:p></o:p>

    当有事件触发时,系统会调用EventQueuepush方法将AWTEvent添加到EventQueue的最后,同时唤醒dispatchThread 

为什么界面会死掉

所以可以看到,Swing的事件分发实际上是同步的,并且都是在dispatchThread这个线程中处理的,也就是说是一个事件一个事件处理的,如果有某一个事件处理的时间非常长的时侯,其他事件就会被堵塞在那里,从现象上看得话,就是界面会死掉,如果界面被其他窗口覆盖之后再回到前面的时侯,会变成一片灰色,这是因为PaintEvent被堵塞而不能被分发出去的缘故。

为什么Modal Dialog(Frame)弹出的时候界面不会死

当在处理事件的时侯如果弹出一个Modal Dialog,那么处理方法会停在那里并等待Modal Dialog销毁,这个时候按照上面的分析,dispatchThread也会停在那里,这样的话其他事件也不会被分发,那么界面也应该会死掉才对。实际上在等待Modal Dialog销毁的过程中,如果能够保证事件可以顺利地分发出去的话,界面当然就不会死。先来看这个例子。

java 代码
  1. package eventqueue;   
  2.   
  3. import java.awt.AWTEvent;   
  4. import java.awt.ActiveEvent;   
  5. import java.awt.Component;   
  6. import java.awt.EventQueue;   
  7. import java.awt.MenuComponent;   
  8. import java.awt.event.ActionEvent;   
  9. import java.awt.event.ActionListener;   
  10.   
  11. import javax.swing.JButton;   
  12. import javax.swing.JDialog;   
  13.   
  14. public class TestEvent {   
  15.     public static void main(String[] args) {   
  16.         final JDialog dlg = new JDialog();   
  17.         dlg.setTitle("Test Event Queue");   
  18.         JButton btn = new JButton("Test");   
  19.         dlg.getContentPane().add(btn);   
  20.         btn.addActionListener(new ActionListener() {   
  21.             public void actionPerformed(ActionEvent e) {   
  22.                 long now = System.currentTimeMillis();   
  23.                 EventQueue theQueue = dlg.getToolkit().getSystemEventQueue();   
  24.                 System.out.println("at least 5000 millis");   
  25.                 while (System.currentTimeMillis() - now < 5000l) {   
  26.                     try {   
  27.                         // This is essentially the body of EventDispatchThread   
  28.                         AWTEvent event = theQueue.getNextEvent();   
  29.                         Object src = event.getSource();   
  30.                         if (event instanceof ActiveEvent) {   
  31.                             ((ActiveEvent) event).dispatch();   
  32.                         } else if (src instanceof Component) {   
  33.                             ((Component) src).dispatchEvent(event);   
  34.                         } else if (src instanceof MenuComponent) {   
  35.                             ((MenuComponent) src).dispatchEvent(event);   
  36.                         }   
  37.                     } catch (Exception ex) {   
  38.                         ex.printStackTrace();   
  39.                     }   
  40.                 }   
  41.                 System.out.println("end");   
  42.             }   
  43.         });   
  44.         dlg.pack();   
  45.         dlg.show();   
  46.     }   
  47. }   

<o:p>  </o:p>

在上面的例子中,当ButtonAction被触发,actionPerformed方法执行的时候,会首先帮助EventQueue分发事件,直到最少5秒之后返回,这时可以看到这个事件处理方法至少执行了5秒钟,但是在这个过程中Dialog仍然可以正常工作,只是因为在这5秒之中并非是Sleep,而是在帮助EventQueue分发事件,如果代码改成
    Thread.sleep(5000);
的话,界面将会死掉。

所以在Modal Dialog弹出的时候,实际上只要在show方法中能够实现类似上面的代码,保证事件可以正常的分发(同时截获父窗口的一些事件,过滤掉一些触发Action的事件),那么父窗口的界面就不会死掉。

当事件处理方法很长时间才能做完该怎么办

<o:p>当事件处理方法需要很长时间才能执行完的话,如果需要保证界面不死的话,还是只能用多线程,虽然上面的方法实现了事件处理的时候界面不死,但是这和一般的事件处理是有不同的,上面的方法实际上在处理的时候什么都没有做,而我们一般需要有自己的操作(比如访问数据库,访问网络,读写操作等需要很长时间才能处理完的工作),不可能做到一边在操作一边处理Event分发,这个时候只有新建一个线程才是正道。</o:p>

<o:p></o:p>

<o:p>  </o:p>

关于EventQueue的一些方法

  <o:p></o:p>

Window.getToolkit().getSystemEventQueue();
   
获取系统的EventQueue<o:p></o:p>

    SwingUtilities.isEventDispatchThread();
   
当前线程是否为EventDispatchThread<o:p></o:p>

    EventQueue.push(EventQueue queue);
   
将一个EventQueue作为当前EventQueuenextQueue,实际上事件是由最后一个EventQueue来分发的<o:p></o:p>

    EventQueue.getNextEvent();
   
获取下一个事件,如果没有,则等到有再返回<o:p></o:p>

   EventQueue.postEvent(AWTEvent theEvent);
  
添加一个Event<o:p></o:p>

 

不过关于很多EventQueueEventDispatchThread的方法都被封装在其实现里面,对外不可视,导致不可能对其进行一些修改,有点不爽。另外在EventQueue中的AWTEvent一般都是给最上层对象的,比如最上层的JDialog或者JFrame,然后由JDialog或者JFrame分发给其他的Component,不过我不知道怎么可以从AWTEvent事件找到真正的拥有者,这一点比较郁闷<o:p></o:p>

 

分享到:
评论

相关推荐

    Swing组建中EventQueue的使用

    本文将深入探讨`EventQueue`的工作原理及其在Swing中的使用,同时也将通过示例代码`SimpleFrameTest.java`来演示如何实际操作。 首先,理解`EventQueue`的概念。`java.awt.EventQueue`是Java AWT(Abstract Window ...

    fest-swing文档

    此外,文档还会介绍如何在测试中访问和操作Swing组件。例如,你可以使用`window()`方法来获取窗口,`button()`或`label()`来选择特定的按钮和标签,然后执行操作,如`click()`或`setText()`。 文档中还会涵盖断言...

    swing分页技术

    此外,还通过`EventQueue.invokeLater`确保Swing组件在事件调度线程中初始化,这是Swing中处理图形组件初始化的标准方式。 2. **分页框架搭建**:`PageTable`类继承自`JFrame`,这是Swing中用于创建窗口的基本类。...

    JAVA 开发 Swing与多线程

    在Java开发中,Swing库是用来构建图形用户界面(GUI)的工具包,而多线程则是提升程序并发性能和响应能力的关键技术。Swing虽然是Java语言的一部分,但它设计为单线程模型,主要是为了简化GUI编程并避免复杂的同步...

    SWING用户界面组件

    在给出的代码中,`NumberSort` 类继承自 `JFrame`,这是Swing中的顶级容器,用于承载所有的GUI组件。`main` 方法通过 `EventQueue.invokeLater` 来确保在事件调度线程中创建和显示GUI,这是Swing应用的标准启动方式...

    Java swing图形界面开发与案例详解_代码

    1. ActionEvent:Swing中最常见的事件类型,用于按钮点击等操作。 2. ActionListener:处理ActionEvent的接口,通过实现其actionPerformed()方法定义事件处理逻辑。 3. EventListenerList:Swing组件中用于存储事件...

    swing演示排序动画

    这是程序的入口类,通过调用 `EventQueue.invokeLater` 方法来确保所有Swing组件在事件调度线程中初始化和显示。创建了一个 `AnimationFrame` 类的实例,并将其设置为可见。 ##### 2. `AnimationFrame` 类 - **功能...

    Java-Swing-MVC使用

    在Java Swing中,模型通常是独立于GUI的对象。例如,在一个计算器应用程序中,模型可能包括数值操作的功能,如加、减、乘、除等。 **示例代码:** ```java public class CalcModel { private String value; ...

    Java swing鼠标拖拽功能源码

    6. **事件传播和处理**:理解和使用Swing的事件模型,包括事件的冒泡和捕获,以及`EventQueue`和`EventListenerList`,以确保事件处理的正确性。 7. **用户体验**:在设计拖拽功能时,还需要考虑用户体验,例如通过...

    java swing拷贝文件进度条

    在Java Swing中实现文件拷贝并同时显示进度条是一项常见的任务,特别是在处理大文件时,让用户了解拷贝进度是提高用户体验的重要方式。下面我们将深入探讨如何使用Java Swing来创建这样一个功能。 首先,我们需要...

    swing-worker-1.1.jar

    Exceptionin thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/jdesktop/swingworker/SwingWorker at com.android.draw9patch.Application$1.run(Application.java:48) at java.awt.event....

    欣赏Swing的大厦结构(意外的发现)

    Swing大厦的顶端是高级特性和工具,如ActionListener(事件监听器)、EventQueue(事件队列)和SwingUtilities( Swing工具类)。事件模型是Swing大厦中的重要组成部分,它允许组件响应用户的交互,如点击按钮或选择...

    java入门补充SwingUI编程完美版资料.ppt

    Java入门补充SwingUI编程是Java编程技术中的一种重要组件,用于设计图形用户界面。下面是Java入门补充SwingUI编程的详细知识点: 一、JFrame框架 * JFrame是一个顶层容器,主要用来设计应用程序的图形用户界面。 *...

    JAVA GUI SWING

    `MainFrameGUI` 类继承自 `JFrame`,这是Swing中创建主窗口的基础类。 #### 3. 静态成员变量 ```java static FileLock lock = null; static WGSLog logger = WGSLog.getInstance(); static CommonUtil common = ...

    如何在Java中从AWT转换为Swing

    1. **组件替换**:AWT的主要组件包括Button、Label、TextArea等,而在Swing中,这些对应于JButton、JLabel和JTextArea。你需要将AWT组件替换为Swing中的J开头的组件。例如,`Button b = new Button("Click");` 变为 ...

    完整版优质java课件 Java基础入门教程 Java编程技术09 Swing UI编程(6学时)(共80页).ppt

    JFrame是Java Swing中的一个顶级容器,它是用来构建应用程序主窗口的基础。它不仅支持展示各种组件,如按钮、文本框等,还允许在多个线程中运行,这在开发复杂的、响应迅速的应用程序时非常关键。创建JFrame通常涉及...

    Java编程技术课件:08Swing UI编程(6学时) new.pptx

    本课程主要围绕Swing中的JFrame框架进行讲解,旨在帮助学习者掌握如何创建和管理Java应用程序的UI。JFrame是Swing中的一个顶级容器,它提供了展示其他组件的基础,支持多线程,使得开发者能够同时处理多个任务。 ...

    Java图形界面开发全练习代码.docx

    Swing中的`JFrame`类是创建窗口的基础。在`SimpleFrame`类中,通过`setSize`方法设置了窗口的默认宽度和高度。而在`Frame`类的`main`方法中,使用了`EventQueue.invokeLater`来确保在事件调度线程中创建并显示`...

    JAVA图形用户界面

    import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.GroupLayout; import javax.swing.GroupLayout.Alignment; import javax.swing.JLabel; import javax.swing.JTextField; import javax...

    java Swing基础教程之图形化实例代码

    `SimpleFrame`类继承自`JFrame`,`JFrame`是Swing中的顶级容器,通常作为窗口的基础。在这个类中,我们设置了窗口的一些属性,如大小、位置、标题和关闭操作。`setExtendedState`方法用来设置窗口的状态,如最大化、...

Global site tag (gtag.js) - Google Analytics