Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 635|回复: 0

[Swing学习]类EventQueue简介

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-9 23:57:00 | 显示全部楼层 |阅读模式
    在Swing的GUI程序中,EventQueue是一个重要的部分,它负责所有AWTEvent(以及其子类)的分发
         EventQueue简单工作原理     简单来讲,在EventQueue中有一个dispatchThread,这是一个线程类,负责事件的分发,当Queue中有事件的时候,它会摘取前面的事件并分发给相应的对象进行处理,等处理完之后再获取下一个,当Queue中没有事件的时候,线程等待。
                                                                                        
    当有事件触发时,系统会调用EventQueue的push方法将AWTEvent添加到EventQueue的最后,同时唤醒dispatchThread。    为什么界面会死掉
         所以可以看到,Swing的事件分发实际上是同步的,并且都是在dispatchThread这个线程中处理的,也就是说是一个事件一个事件处理的,如果有某一个事件处理的时间非常长的时侯,其他事件就会被堵塞在那里,从现象上看得话,就是界面会死掉,如果界面被其他窗口覆盖之后再回到前面的时侯,会变成一片灰色,这是因为PaintEvent被堵塞而不能被分发出去的缘故。  
      
      
          为什么Modal Dialog(Frame)弹出的时候界面不会死     当在处理事件的时侯如果弹出一个Modal Dialog,那么处理方法会停在那里并等待Modal Dialog销毁,这个时候按照上面的分析,dispatchThread也会停在那里,这样的话其他事件也不会被分发,那么界面也应该会死掉才对。实际上在等待Modal Dialog销毁的过程中,如果能够保证事件可以顺利地分发出去的话,界面当然就不会死。先来看这个例子。 mport javax.swing.JDialog;
    import javax.swing.JButton;
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    import java.awt.EventQueue;
    import java.awt.AWTEvent;
    import java.awt.ActiveEvent;
    import java.awt.event.PaintEvent;
    import java.awt.Component;
    import java.awt.MenuComponent; public class TestEvent {
         public static void main(String[] args) {
             final JDialog dlg = new JDialog();
             dlg.setTitle("Test Event Queue");
             JButton btn = new JButton("Test");
             dlg.getContentPane().add(btn);
             btn.addActionListener(new ActionListener(){
                 public void actionPerformed(ActionEvent e){
                     long now = System.currentTimeMillis();
                     EventQueue theQueue = dlg.getToolkit().getSystemEventQueue();
                     System.out.println("at least 5000 millis");
                     while (System.currentTimeMillis() - now < 5000l) {
                         try {
                             // This is essentially the body of EventDispatchThread
                             AWTEvent event = theQueue.getNextEvent();
                             Object src = event.getSource();
                             if (event instanceof ActiveEvent) {
                                 ((ActiveEvent) event).dispatch();
                             }
                             else if (src instanceof Component) {
                                     ((Component) src).dispatchEvent(event);
                             }
                             else if (src instanceof MenuComponent) {
                                 ((MenuComponent) src).dispatchEvent(event);
                             }
                         }
                         catch (Exception ex) {
                             ex.printStackTrace();
                         }
                     }
                     System.out.println("end");
                 }
             });
             dlg.pack();
             dlg.show();
         }
    } 在上面的例子中,当Button的Action被触发,actionPerformed方法执行的时候,会首先帮助EventQueue分发事件,直到最少5秒之后返回,这时可以看到这个事件处理方法至少执行了5秒钟,但是在这个过程中Dialog仍然可以正常工作,只是因为在这5秒之中并非是Sleep,而是在帮助EventQueue分发事件,如果代码改成Thread.sleep(5000);
    的话,界面将会死掉。     所以在Modal Dialog弹出的时候,实际上只要在show方法中能够实现类似上面的代码,保证事件可以正常的分发(同时截获父窗口的一些事件,过滤掉一些触发Action的事件),那么父窗口的界面就不会死掉。     当事件处理方法很长时间才能做完该怎么办     当事件处理方法需要很长时间才能执行完的话,如果需要保证界面不死的话,还是只能用多线程,虽然上面的方法实现了事件处理的时候界面不死,但是这和一般的事件处理是有不同的,上面的方法实际上在处理的时候什么都没有做,而我们一般需要有自己的操作(比如访问数据库,访问网络,读写操作等需要很长时间才能处理完的工作),不可能做到一边在操作一边处理Event分发,这个时候只有新建一个线程才是正道。 关于EventQueue的一些方法     Window.getToolkit().getSystemEventQueue();
         获取系统的EventQueue     SwingUtilities.isEventDispatchThread();
         当前线程是否为EventDispatchThread     EventQueue.push(EventQueue queue);
         将一个EventQueue作为当前EventQueue的nextQueue,实际上事件是由最后一个EventQueue来分发的     EventQueue.getNextEvent();
         获取下一个事件,如果没有,则等到有再返回    EventQueue.postEvent(AWTEvent theEvent);
        添加一个Event   不过关于很多EventQueue和EventDispatchThread的方法都被封装在其实现里面,对外不可视,导致不可能对其进行一些修改,有点不爽。另外在EventQueue中的AWTEvent一般都是给最上层对象的,比如最上层的JDialog或者JFrame,然后由JDialog或者JFrame分发给其他的Component.  
       
       
                            
         
       
                            
         
       

       
         
         
          
          

            
          

            
          
         
       

      


    源码下载:http://file.javaxxz.com/2014/11/9/235700078.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 07:42 , Processed in 0.362966 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表