AWT/Swing中的Repaint, paint, update
1.? ? Core java ch 14 confusion
读Core java 卷I,14.1节的时候,有一段用于在UI上面移动小球的代码,用了paint方法,而不是我们平常用的比较多的repaint,而且jdk文档中明确注明了不推荐直接调用paint,所以有些困惑。
对此,书中的解释是:But if you try to call?comp.repaint()in this program, you’ll find that the panel is only
repainted after the?addBall?method has returned.?
2.? ? Testing, repaint with paint
查了相关文档,发现paint和repaint的区别还是很大的。Paint方法一般在UI事件的callback中被调用,以进行组件的绘制。假如直接调用paint,绘制将发生在AWT/Swing的事件机制之外。而repaint会向AWT注册一个异步请求,告诉AWT哪个组件需要绘制。这个请求将触发组件的update方法。假如对于同一个组件,在第一个repaint被解决之前,有多个repaint被调用,那么这多个请求将合并为一个请求。
在实例代码中,addBall方法是在事件callback函数(event->addBall())中调用的,在按钮按下触发的callback函数开始之后,addBall才会执行。假如这里用repaint,那么在callback函数(event->addBall())执行结束之后,所有的由repaint注册的update(其实就是paint)方法才会执行,根据前面的规则,所有的repaint请求被合并了。因而,假如用repaint,将会看到球直接移动到了最终位置。
把方法改成repaint,在repaint方法和paint方法中打出log,
看到输出结果:
==============? repaint
==============? repaint
==============? repaint
================== paint
3.? ? AWT/Swing的历史
Java1.0 刚出现的时候,包含了一个用于基本的UI设计的包,名叫AWT (Abstract Window Toolkit)。AWT将绘制UI的任务委托给了目标平台自带的GUI绘制工具箱。但是AWT不能很好的解决平台之间的差异。
1996年Netscape创立了IFC(Internet Foundation Class),采取了与AWT完全不同的工作方式。在这种工作方式下,目标平台的GUI绘制工具箱负责创立和绘制窗口,而像按钮、菜单这样的客户界面元素由IFC绘制到窗口上。
之后,Sun和Netscape合作,完善了IFC,创立了Swing。Swing作为java1.1的扩展部分使用,并最终在java1.2成为了标准库的一部分。
从Swing的实现方式来说,Swing没有完全替代AWT,而是基于AWT架构之上。Swing提供了能力更为强大的客户界面组件,而且需要使用AWT的事件解决机制。也就是说,不论是AWT还是Swing,UI的绘制都依赖于callback机制:
a.? ? 监听器对象是一个实现了特定监听器接口的类的实例。
b.? ? 事件源(例如按钮)是一个能够注册监听器对象并发送事件的对象。
c.? ? 当事件(例如点击按钮)发生时,事件源将事件对象传递给所有注册的监听器。
d.? ? 监听器对象将对事件作出响应(执行callback函数)
AWT和Swing依赖于组件的paint方法绘制UI。这里需要注意的是,一般情况下,应该避免在callback之外绘制UI,由于这样做跳出了AWT/Swing的事件机制,很容易引起UI绘制中的混乱。因而不推荐直接调用paint。
4.? ? Lightweight vs heavyweight
从应用开发者的角度来说,二者基本上没有区别:他们都是调用API paint对组件进行绘制。然而,lightweight完全是用java code 开发的,所以在实现机制上还是有细微的差别。由于Lightweight组件必需绘制在heavyweight组件上,当heavyweight组件被告知需要调用paint的时候,它应该将绘制信息传递给其所有的子lightweight组件。而且,lightweight具备透明性,着意味着update不会清空lightweight的背景(这一点有别于heavyweight组件)。关于update方法的详细信息将在稍后阐述。
a)? ? ? Lightweight: 重用 heavyweight组件。
b)? ? ? Heavyweight: opaque, native windows.
5.? ? System trigger vs application trigger
系统触发的事件和应用触发的时间最终要调用组件的paint方法,所以说二者没有本质区别。
a)? ? ? System trigger:新建组件,resize,从“破损”的状态下“修复”(没有显示不完全à显示完全)。
?i.? ? ? ? ? ?Things with AWT
????1.? ? ? ?AWT决定需要绘制的部分
? ? 2.? ? ? ?AWT导致事件分发线程触法组件的paint方法
b)? ? ? App triggered: 由客户动作触发的事件,导致UI的变化。在这种情况下,可以通过调用组件的repaint方法绘制组件。假如组件较为简单,可以调用repaint的无参数版本,以绘制整个组件;反之,假如组件较为复杂,则可以调用repaint的有参数版本,从而仅仅绘制需要的部分。为了响应状态的变化(MVC模型),程序决定绘制组件的部分还是一律。
?i.? ? ? ? ? ?Things in AWT
????1.? ? ? 程序调用组件的repaint方法,该方法向AWT注册一个异步请求,告诉AWT哪个组件需要绘制。这个请求将触发组件的update方法。假如对于同一个组件,在第一个repaint被解决之前,有多个repaint被调用,那么这多个请求将合并为一个请求。
? ? 2.? ? ? ?对于heavyweight组件,默认情况下,Update清空组件需要升级的部分,而后调用组件的paint方法,Update方法支持所谓的“增量绘制”。而对于lightweight组件,Update直接调用paint。因而对于lightweight组件来说,update和paint没有区别。
6.? ? AWT vs Swing
从Swing的实现方式来说,Swing没有完全替代AWT,而是基于AWT架构之上,并对AWT进行了加强。加强的特性包括:
a.? ? Double Buffer Support: 这是Swing区别于AWT的最明显特性,该特性为每一个container hierarchy提供了唯一个offscreen(幕后,区别于onscreen) Double Buffer。假如这个特性被enabled(默认情况下enable),那么graphics对象将被转成offscreen graphics,接下来,绘制过程在double buffer中进行,绘制结束后,offscreen graphics会被原始的graphics对象拷贝回组件。
b.? ?Additional Paint Properties:Swing添加了少量属性,以提高内部绘制算法的效率。这些属性用于形容两类问题:
????a)? ? ? 透明性,在绘制lightweight组件的时候,可能不会绘制出组件的所有像素,所以必需从container hierarchy向上追溯到第一个heavyweight组件,最后进行“back-to-front”的绘制操作。
????????i.? ? ? ? ? ?opacity:假如为true,组件同意绘制自己的一律像素。对于大多数组件,opacity为true。
? ? ?b)? ? ? 重叠组件:lightweight组件之间可能相互重叠。
? ? ? ? i.???????????[endif]IsOptimizedDrawingEnabled:假如为true,表示没有任何直接子组件是重叠的。通过检查这个属性,Swing repaint可以很容易的查找组件之间的重叠关系。
c.? ? UI Delegate: 绝大多数Swing组件的绘制被代理商给UI Delegate(separated Look-and-feel 对象)
d.? ? RepaintManager:用于最大化Swing组件的绘制效率。
e.? ? Swing的绘制机制和AWT相似,但是paint方法的实现是不一样的。
? ?a)? ? ? Paint依次调用三个方法,paintComponet–>paintBorder –>paintChild
? ?b)? ? ? 假如绘制请求来自于顶层heavyweight对象(JFrame,JDialog,JWindow,JApplet),事件分发线程调用该heavyweight对象的paint方法:
? ? ? ? ? ? i.? ? ? ? ? ?假如double Butter 特性被enabled,将graphics对象转为offscreen graphics对象。
? ? ? ? ? ? ii.? ? ? ? ? 调用paintCompnent
? ? ? ? ? ? iii.? ? ? ? ? 调用paintBorder
? ? ? ? ? ? iv.? ? ? ? ? ?调用paintChildren (传入属性值,opacity,isOptimizedDrawingEnabled)
? ? ? ? ? ? v.? ? ? ? ? ?假如double Butter 特性被enabled,将offcreen graphics转为原始的graphics对象
? ? ?c)? ? ? ?假如绘制请求来自来自于对repaint的调用
? ? ? ? ? ? ? i.? ? ? ? ? ?repaint在组件的RepainManager 上注册一个repaint请求,repaintManger用invokeLater将一个runnable(用于稍后解决请求)放入事件分发线程。
? ? ? ? ? ? ? ii.? ? ? ? ? ?当runnable运行的时候,会使得repaintManager调用组件的paintImmediately 方法。PaintImmediately方法相似updtate方法。在Swing中,永远不会调用update方法。
? ? ? ? ? ? ? ?iii.? ? ? ? ? ?利用clip、opacity和isOptimizedDrawingEnabled信息,决定从哪个根组件开始绘制。
? ? ? ? ? ? ? ?iv.? ? ? ? ? ?转到b)
Reference
https://docs.oracle.com/javase/7/docs/api/java/awt/Component.html
https://www.oracle.com/technetwork/java/painting-140037.html#triggers
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » AWT/Swing中的Repaint, paint, update