JavaSwingAwt高级事件机制.ppt

上传人:max****ui 文档编号:11496759 上传时间:2020-04-25 格式:PPT 页数:34 大小:1.52MB
返回 下载 相关 举报
JavaSwingAwt高级事件机制.ppt_第1页
第1页 / 共34页
JavaSwingAwt高级事件机制.ppt_第2页
第2页 / 共34页
JavaSwingAwt高级事件机制.ppt_第3页
第3页 / 共34页
点击查看更多>>
资源描述
Tektronix(China)Co.,LTDNO.1,JavaSwing&AWT高级事件机制,HaojunRenTektronix2011.09,Tektronix(China)Co.,LTDNO.2,引子:一个故事,这是一个封闭的且非常注重安全的城市外界沟通的渠道只有一个单向环形高速公路任何物资运输必须通过卡车单向运输到另一个点这个城市从外界(森林和河流)获取木材和水等通过自来水厂和木材厂加工成自来水和家具并将这些产品运输给居民或学校使用某一种特供物资必须由一种高性能,速度极快的卡车运输,且一刻都不能耽误,Tektronix(China)Co.,LTDNO.3,引子:一个故事,开始一切都很正常,直到有一天有个质量不好的卡车出发了,半路严重抛锚,司机下来修车。但是这车太难修,一修就是几天,结果后面的汽车无法前进,各种物资无法按时运到目的地,最严重的是,有若干辆运送特供物资的卡车也被堵着市民急了,市长急了,但没有任何解决办法,于是城市暂时瘫痪了经过这次教训,市政府决议,“由于堵车情况无法避免,但运送特供物资的卡车是无论如何不能耽误”,于是给出三个解决方案,Tektronix(China)Co.,LTDNO.4,引子:一个故事,解决方案:开辟一条新的运输线路,来行驶质量不好的卡车,其他好卡车不小心驶到这条运输线路的时候,交警会指挥把它们强制驶回单向环形高速公路质量不好的卡车一旦抛锚,交警会指挥首先让其他好卡车先通过,在其他好卡车通过之前,它不能做修理这个问题很棘手,交给专业公司外包解决,Tektronix(China)Co.,LTDNO.5,Java进程与线程,Java进程(Process)一种于自身定址空间中执行的独立程序。所谓多工(Multitasking)操作系统,会周期性的将CPU时间划分给每个进程,使操作系统得以同时执行一个以上的进程,并让每一个进程都像独立运作一样Java线程(Thread)Java线程(Thread)是进程(Process)中的一个“单一连续控制流程”(Asinglesequenctialflowofcontrol)。一个进程(Process)可拥有多个并行(Concurrently)的线程,Tektronix(China)Co.,LTDNO.6,Java进程,当Swing界面程序启动后,虚拟机(JVM)会启动3个线程主线程Swing事件派发线程EDT(Event-dispatchingthread)系统工具包线程,Tektronix(China)Co.,LTDNO.7,主线程,通常意义下的Java线程,该线程从Java进程启动到终止,贯穿始终例如:一个Java应用程序(进程)启动,通过main方法,主线程创建并启动;通过System.exit方法,主线程销毁,进程结束,Tektronix(China)Co.,LTDNO.8,GUI系统的事件模型,事件派发线程(Event-dispatchingthread)和事件处理线程单线程模型-事件的派发线程和处理线程是同一线程-事件从事件队列中取出之后,立即在当前线程中处理,处理完后才取下一个事件继续循环。在同一线程中完成事件派发和组件的模型数据处理(更新界面)多线程模型-事件的派发线程和处理线程是分别不同一线程-事件派发线程负责从事件队列中获取事件-事情处理线程负责组件的模型数据的处理-当获取到新的事件后,它会启动新的事件处理线程,并将事件交由此线程处理,之后派发线程并不等待事件处理线程完成,而是立即获取下个事件进行派发,Tektronix(China)Co.,LTDNO.9,GUI系统的事件模型,Tektronix(China)Co.,LTDNO.10,GUI系统的事件模型多线程模型,存在多个处理线程同时处理,可能产生同步问题-程序数据的同步出现问题-组件的数据模型产生同步问题GUI系统来说必须考虑组件的外观同其数据模型一致需要采用复杂的同步机制来保持数据模型的同步,对于系统的开发者和应用开发者来说都是很高的要求该模型很少被现有的GUI系统采用,Tektronix(China)Co.,LTDNO.11,GUI系统的事件模型单线程模型,事件处理线性且处理顺序固定,避免同步问题缺陷是线程独占为了避免长时间事件处理占据线程,应用程序往往在事件处理方法中启动其他线程来完成事件的处理,而将事件派发线程留给耗时短的事件处理为了保证界面的一致性,使用单线程模型GUI系统的应用需要将对组件的操作放在事件派发线程上完成,毕竟组件的操作(主要是刷新)是耗时短暂的,Tektronix(China)Co.,LTDNO.12,GUI系统的事件模型Awt和Swing单线程模型,Awt和Swing组件操作是非线程安全的,因为几乎所有的组件操作方法都未做同步处理,所以不建议采用多线程。(怎么实现对组件操作方法的同步处理?)Awt组件操作是线程安全的,因为它内部采用许多复杂的同步机制来完成这个操作Swing和Swt的不同是Swt在运行时检查组件操作是否在派发线程上,如果不是则抛出异常警告,而Swing则需要程序员自己做控制SwingUtilities.isEventDispatchThread(),判断当前线程是否是Awt事件派发线程,Tektronix(China)Co.,LTDNO.13,GUI系统的事件模型Awt和Swing单线程模型,这是一个封闭的且非常注重安全(线程安全)的城市(用户界面)外界沟通的渠道只有一个单向环形高速公路(事件队列循环)任何物资运输必须通过车辆(各种事件)单向运输到另一个点这个城市从外界(森林和河流)获取木材和水等(鼠标、键盘等原生事件)通过自来水厂和木材厂(各种组件)加工成自来水和家具(逻辑事件)并将这些产品运输给居民或学校(消费逻辑事件的事件处理器)使用某一种特供物资(响应界面绘制)必须由一种高性能,速度极快的卡车(repaint)运输,且一刻都不能耽误,Tektronix(China)Co.,LTDNO.14,GUI系统的事件模型Awt和Swing单线程模型,开始一切都很正常,直到有一天有个质量不好的卡车(耗时性长事务)出发了,半路严重抛锚,司机下来修车。但是这车太难修,一修就是几天(长耗时,且线程独占),结果后面的汽车(事件)无法前进,各种物资无法按时运到目的地(堵塞),最严重的是,有若干辆运送特供物资的paint(响应界面绘制)的卡车也被堵着市民急了,市长急了,但没有任何解决办法,于是城市暂时(用户界面)瘫痪(失去响应,灰框GrayRectangle)了经过这次教训,市政府(事件派发线程)决议,“由于堵车情况无法避免,但运送特供物资的paint(响应界面绘制)卡车是无论如何不能耽误”,于是给出三个解决方案,哪三个?,Tektronix(China)Co.,LTDNO.15,GUI系统的事件模型Awt和Swing单线程模型,解决方案:开辟一条新的运输线路(非EDT线程),来行驶质量不好的卡车(耗时性长事务),其他好卡车(特别是paint的卡车)不小心驶到这条运输线路的时候,交警会指挥把它们强制驶回单向环形高速公路(事件队列循环)-InvokeLater质量不好的卡车(耗时性长事务)一旦抛锚,交警会指挥首先让其他好卡车先通过,在其他好卡车通过之前,它不能做修理(被EDT线程堵塞,等待返回)-InvokeAndWait这个问题很棘手,交给专业公司外包解决(SwingWorker),Tektronix(China)Co.,LTDNO.16,Swing事件派发线程EDT(Event-dispatchingthread),负责把事件队列里的事件派发到相应组件上,并调用绘制方法更新界面事件(Event)事件队列(EventQueue)事件派发线程EDT,Tektronix(China)Co.,LTDNO.17,事件(Event),发送给JavaGUI系统的消息,该消息通知JavaGUI系统某种事情已经发生,要求作出响应。事件具有组播性。根据事件来源,可归类为三种:计算机输入输出设备产生的中断事件GUI系统触发的逻辑事件应用程序触发的事件,Tektronix(China)Co.,LTDNO.18,事件(Event),计算机输入输出设备产生的中断事件最原生的底层事件需要组件做深入处理,籍此触发更高抽象层次具有语义的逻辑事件GUI系统扩展自定义组件往往需要编写处理这些事件,派发高级逻辑事件这些事件对应的有MouseEvent、KeyEvent、FocusEvent等,实现鼠标,键盘,焦点同GUI系统的交互操作由系统工具包线程负责捕获AWT-Windows线程AWT-SolarisAWT-Linux,Tektronix(China)Co.,LTDNO.19,事件(Event),GUI系统触发的高级逻辑事件计算机输入输出设备产生的中断事件经过组件的处理后发出的高级逻辑事件Swing的JButton产生的ActionEvent界面处理的高级逻辑事件重绘(repaint-Component)重布局(validate-Container,revalidate-JComponent)更新UI(updateUI-Swing组件实现类)接收到EXPOSE事件或GUI系统显式调用上述方法后触发的事件(当被遮挡的窗口被暴露时,AWT-Windows线程获得到了这个EXPOSE事件),Tektronix(China)Co.,LTDNO.20,事件(Event),应用程序触发的事件有两种触发方式:事件通过方法调用被添加到系统事件队列进行派发-通过postEvent、repaint及invokeLater等方法,向系统事件队列添加事件-调度机制。事件被添加到系统事件队列后触发过程结束,事件的处理要在事件派发线程EDT上等待执行-触发事件的线程和事件派发线程可以不是同一个线程通过调用组件的派发方法进行触发-通过fireEventXXXX(例如fireActionPerformed,fireTableDataChanged)触发-函数调用机制。事件对象不会被放到系统事件队列中去,而是直接传递给事件处理方法处理-这种事件触发方式要求事件处理线程必须同时是事件派发线程,Tektronix(China)Co.,LTDNO.21,事件队列(EventQueue),事件队列是线性的,同步的一个事件需要等待在它之前的事件先处理完毕后,才被处理压栈出栈模式排队:依次排队,末端进入,顶端弹出处理:先进先处理,后进后处理Swing的事件队列做了很多优化,Tektronix(China)Co.,LTDNO.22,事件派发线程EDT,单线程模式职责分明,任何GUI请求都应该在EDT线程中被调用非常忙碌,需要处理的GUI请求非常多,包括窗口移动、组件自动重绘、刷新,所以耗时极短的请求可在EDT线程中被调动,任何与GUI无关的处理不要由EDT线程来负责一旦Swing组件被实现或者显示,所有改变组件状态的代码或者依赖于组件状态的程序代码,全部需要给EDT执行-setVisiable(true)显示-show()显示-pack()实现-父组件已经被实现或者显示上述4种方法(或之一)出现以前,所有的关于界面的代码一般是安全的,但还是强烈建议当在EDT线程里面执行;上述4种方法(或之一)出现以后,所有的关于界面的代码都必须在EDT线程里面执行;(见InvokeLater篇),Tektronix(China)Co.,LTDNO.23,事件派发线程EDT,界面处理的高级逻辑事件,可以被非EDT线程所调用,一旦被调用,上述方法并不是立刻并执行,而是被挂到事件队列里,由EDT线程去执行-重绘(repaint-Component)-重布局(validate-Container,revalidate-JComponent)-更新UI(updateUI-Swing组件实现类)负责将事件队列中的事件进行预处理,比如多个连续的Paint事件合并成一个,Tektronix(China)Co.,LTDNO.24,事件派发线程EDT,理解JDK源码-JComponent中的revalidate方法可见,revalidate在EDT和非EDT线程中都可被调用,Tektronix(China)Co.,LTDNO.25,特殊事件同步的绘制请求,paintImmediately方法,立即绘制当前界面如果根据事件队列先进先出原则,在EDT线程中调用paintImmediately,是不是被挂到队列最后?paintImmediately是不是意味着它被插到事件队列的最前面,装模作样排个队,在被第一时间处理?实际上是插队,连排队都不要。它比任何其他事件的优先级最高,包括当前正在处理的事件。EDT当收到paintImmediately的时候,必须放下手中正在处理的活(不管这个活干了多少),当paintImmediately处理完毕,继续干它先前的活。这是Swing事件队列机制的优化表现,Tektronix(China)Co.,LTDNO.26,系统工具包线程,负责捕获操作系统底层事件转换和翻译成Swing所认识的事(MouseEvent、KeyEvent、FocusEvent)放入到Swing的系统事件队列(EventQueue)EDT线程中排队等候这些事件,一旦被触发,将会被分派到Swing组件中事件处理和响应。,Tektronix(China)Co.,LTDNO.27,一个Swing事件模型的示例,PumpanEvent-Dispatch&ProcessEvent-MouseListener.mousePressed-fireActionPerformed-ActionListener.actionPeformed-Dodatabasequeryanddisplayresulttoatable-ReturnfromactionPerformed-ReturnfromfireActionPerformed-ReturnfromMouseListener.mousePressed-PumpanotherEvent,Tektronix(China)Co.,LTDNO.28,InvokeLater&InvokeAndWait,非EDT线程的对组件的并发调用需通过-invokeLater(runnable)-invokeAndWait(runnable)使请求插入到队列中等待EDT线程去执行,Tektronix(China)Co.,LTDNO.29,InvokeLater,异步方式,立即返回ThiswillhappenafterallpendingAWTeventshavebeenprocessed具体何时执行请求并不确定,视EDT线程是否空闲SwingUtilies.invokeLater=EventQueue.invokeLater-保证代码在EDT线程中运行-可能存在pack或者setVisible的时候,由另一线程去获取getPreferredSize而抛出异常。有时候这个异常并不是每次都出现。,Tektronix(China)Co.,LTDNO.30,InvokeLater,Tektronix(China)Co.,LTDNO.31,InvokeAndWait,同步方式,阻塞调用invokeAndWait线程,直到EDT线程处理完当前请求ThiscallblocksuntilallpendingAWTeventshavebeenprocessedand(then)doRun.run()returns主要作用是等待EDT处理组件结束后,取得组件相关界面数据避免死锁,不能在EDT线程中被调用,否则程序会抛出异常,请求也不会去执行invokeAndWait在EDT线程中调用,那么首先将请求压进事件队列,然后EDT线程便被block(因为它就是调用invokeAndWait的当前线程)等待请求结束通知它继续运行,而实际上请求将永远得不到执行,因为它在等待队列的调度使EDT执行它,这就陷入一个僵局-EDT等待请求先执行,请求又等待EDT对队列的调度。彼此等待对方释放锁是造成死锁的四类条件之一,Tektronix(China)Co.,LTDNO.32,InvokeAndWait,Tektronix(China)Co.,LTDNO.33,InvokeAndWait,Tektronix(China)Co.,LTDNO.34,SwingWorker,在JavaSwing&Awt高级事件机制-SwingWorker具体阐述,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!