加速GTK树视图
我正在为Maemo平台开发一个应用,使用的是pygtk,但树形视图的渲染速度似乎有点问题。因为这个应用是个媒体控制器,所以我在界面中使用了过渡动画。这些动画会在用户操作界面时,让控制按钮滑入视野。不过,树形控件的速度比较慢。
把控件在屏幕中间移动的时候速度还可以,但如果要显示的单元格多了,帧率就会明显下降。更让人烦的是,如果只有标题行和行标签在显示,帧率就能保持得很好。
根据这个情况,我怀疑GTK的树形视图每次只要有一行像素显示出来,就会重新绘制整个单元格。有没有办法强制GTK把整个控件绘制到一个缓冲区里,即使有些部分在屏幕外,然后在动画时用这个缓冲区来绘制控件呢?
另外,使用Viewport向上滚动和使用布局面板向下移动控件之间有什么区别吗?我本以为Viewport会更快,但我试了两种方式后,没感觉到有什么明显的差别。
我知道这并不是GTK最初设计的目的。我还尝试过pygame,但我更希望能用一些更高级的实现,里面自带基于控件的事件处理。而且pygtk的好处是可以在Windows上运行,开发起来更方便。
1 个回答
我自己没做过这个,但你可以试着自己实现缓存。与其使用预定义的单元格渲染器,不如自己实现一个单元格渲染器(可以把它当作实际渲染器的包装),同时缓存图像。
在PyGTK中,你可以使用gtk.GenericCellRenderer
。在你的装饰单元格渲染器中,当需要渲染时,可以这样做:
- 保持一个离屏图像的缓存(或者更好的是,保持一个大的图像)和一个大小的缓存
- 如果需要预测大小或渲染,就根据相关属性创建一个键
- 如果这个键在缓存中存在,就使用缓存的图像,把它绘制到你得到的可绘制区域上
- 否则,先让实际的单元格渲染器完成工作,然后再复制它
最后一步也意味着,第一次渲染单元格时,缓存会带来一些额外的开销。你可以通过使用缓存策略来稍微减轻这个问题。你可能想根据渲染值的分布尝试不同的方法:
- 如果所有单元格都是独一无二的,那就没什么好做的,只能缓存所有内容,直到某个限制,或者使用某种最近最少使用(MRU)策略
- 如果你有某种齐夫分布,也就是说,有些单元格非常常见,而其他单元格非常稀少,你应该只缓存高频单元格,放弃稀有单元格的缓存开销。
话虽如此,我不能确定这是否会有任何区别。我从一个类似的问题中得到的经验是,涉及文本的任何东西通常都比较慢,因此缓存是有意义的——抱歉我不能给出更简单的建议。
在你尝试之前,你也可以简单地写一个装饰单元格渲染器,统计你的单元格实际渲染的次数,并获取一些时间信息,这样你就能了解热点在哪里,以及缓存这些值是否有意义。