基于双缓存的嵌入式画面系统的设计

一、需求

  这次的嵌入式项目中的画面,每次迁移的时候总是会发生无法忍受的闪屏。系统中的画面时基于AWT的,考虑下来闪屏主要是以下两个方面:

  1)、画面生成特别慢,应该是AWT中实现的功能太多,影响了画面生成的效率

  2)、画面刷新时,总是会先刷背景,再画内容。由于硬件性能的影响,整个刷新过程可以看到很明显的闪屏。

 修正案1:

  针对以上的疑点1),通过以下两种途径来修正:

  1)、整个画面生成后,再显示到屏幕上。降低画面生成时的时间消耗对显示的影响

  2)、将生成后的画面缓存,提升画面生成的效率。

  修改完成后发现,虽然画面的生成时间有300毫秒左右提升到70毫秒,但是闪屏依旧。如此看来应该是硬件平台上的AWT实现的问题。

 修正案2:

  重新实现一个有限功能的画面系统,在这个画面系统中最终生成一个图片,最后直接画到画面上。

 

二、设计

 1、设计目标

   1)、绝对不闪,只是实现50毫秒级的画面描画,而不闪屏。

   2)、实现业务中所有需要的功能(还好是个嵌入式的系统,画面不超过40个)。

   2)、提供类似于AWT的接口,方便业务人员的实装。

 2、画面系统中的关键概念:

  MainFrame:对应一个AWT的Frame,负责画面中最终描画,和AWT事件的分发。

  View:逻辑画面,所有画面的基类。

  Dialog:逻辑对话框。本来不需要重新实现Dialog,可是JVM实现的Dialog总是会影响后面画面的描画,并且效率奇低。只能自己做一个。

  Panel:所有控件的容器。View中的控件管理都会委托给Panel。

  Canvas:画布,一个Canvas对应一个BufferedImage,最终画面的显示,就是将这个BufferedImage显示出来。

  Component:控件的基类。实现了Lable、TextField、Button、List、Panel、ScrollPanel。

 3、设计思想

   每个View对应一个Canvas,View中的每个控件的操作都会映射到这个Canvas中,提升画图的效率。一个控件状态的变更,不会导致整个view的重绘,而只会重绘这个控件。但是提供重绘这个View重绘的接口。

   画面的迁移只是View的逻辑迁移,不会导致AWT的画面迁移。

   支持Panel的嵌套,以方便共同画面模块的实现。

 

三、实现要点

 1、控件系

 

 类图

  所有的控件都继承自Component,Component类实现了所有控件的共同属性,如前景背景,字体图片,可视等等。所有的控件都必须放在panel中,View中其实就是放了一个RootPanel。只有实现了Scrollable接口的控件才能放入ScrollPanel中,其实最好是Panel实现Scrollable,而现在的项目里没有用到所以就没有实现。

 2、画面管理系

  类图

  系统中的可获得焦点控件都要实现Focusable接口,而View类包含一个Focusable的属性。一个画面只能有一个控件获得焦点,所以我把焦点监听放到了View中,以方便管理。而整个系统中只有TextField实现了Focusable。

  系统Activable监视鼠标的压下事件,这可以使控件可以在控件拖动时实现更大的灵活性。比如滚动条,开始滚得时候可能在滚动条上,而托托鼠标可能就偏了,最为继续跟踪这个事件就通过Activable来保存这个控件。系统中只有滚动条实现了这个接口。

  整个系统中只会有一个MainFrame的实例,它负责将View生成的图像描画到屏幕上,并将画面上的鼠标事件发送给View。由于系统中的画面不支持 键盘,所以不实现键盘事件。ViewManagerImp中包含了一个View和Dialog的引用,他们都描画都会被委托为MainFrame。Dialog的描画最终也会委托给View,以防止短时间内画 面的多次描画导致的闪屏。

  View的初始属性的设置与迁移共同参数的生成都由ViewManager管理,而View对象的实际生成由ViewFactory完成,不过提供了一个根据类名通过反射生成的实例的默认实现。这里通过ViewManger和ViewFactory把对象的生成与属性的设置进行分离,以便于扩展。

四、改善点

 1、将画布放入到每个控件中

  在现有系统中,所以控件的描画都会委托为View中的Canvas,这虽然提升了性能,但是也使得控件的描画有许多限制。比如描画工程只能由控件自己完成,而不能由上层来控制。如List其实有两种状态,一种是直接放到Panel中,不需要变更大小。直接描画就可以;而当其放在ScrollPanel中时,则可以改变大小,由ScrollPanel来滚动。在现有系统中就需要List区分这两种行为。而如果是每个控件都有自己的Canvas,那么父容器就可以选择做出不同的行为,这个应该更合理,更自由。当然,也是需要一定的性能损耗的。

 2、控件初始化的时机变更

  现有系统的空间初始化是与AWT类似的,在addComponent时初始化,这就有很多时机的问题。现在想来还是SWT那种直接在构造函数中传父容器的方式更简单,方便。

 3、MainFrame与View的关系

  现在是view是MainFrame的属性,其实不需要,View应该有ViewManager完全控制。ViewManager会将view的描画委托为MainFrame。

 4、为了提升画面更新的效率,考虑引入修改缓存的概念

  现在的系统是任何一个控件的状态改变都会直接反映到屏幕上,如TextField的输入等。

  当画面上有多个自主更新的控件时,并且不希望每个控件的更新都导致画面刷新,这时可以将图像的修改缓存,然后再一个特定时机一起刷新,当然这个时间间隔必须很小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值