Qt 中经常使用 Model-View 模型来创建列表等视图,这样设计程序结构的好处是能将数据部分和界面完全分离。其中 Model 负责数据的准备与加工,View 提供了具体的对外显示的 Widget,而 Delegate 用作在 View 上绘图的模块。而对于现代的图形程序设计,对动画效果的要求更多,需要这三个模块配合来创建动画效果。
最终效果
动画原理
由于 Model-View 模式的基本流程是由 Model 提供数据由 Delegate 绘图再由 View 显示。所以如果想要创建动画,首先必然是由 Model 出发,发送 DataChanged 信号通知 View 重绘某个数据。
上面的代码实现了所说的功能,其基本思想就是使用一个 Timer 来不断发送 DataChanged 信号来维持界面重绘。其中控制 Timer 的 interval 可以控制动画的刷新率。
动画的绘制
绘图的主要代码就是通过 Model 获取当前 Item 是否应该显示动画等信息,再根据一个变量代表的动画帧来绘图。Delegate 的核心代码如下:
这里用了一个巧妙的方法来获得动画帧,就是使用 Unix 时间戳。控制 Index 变量的计算可以控制动画的速度。
动画的几个要素
1. 动画的开始时间(即 Timer 的启动时间)。这里的具体需求是点击某个 Item 之后开始动画。
2. 动画的结束时间(即 Timer 的停止时间)。此时应该是这个 Item 完成 Click 的某些动作,收到对应的 Callback/信号时结束动画。
3. 动画所应用到哪个位置。也就是说要能从 Model 中获取出,当前哪些位置的 Item 是有动画效果的,要能区别出有动画和无动画的 Item。
完整的示例
这里有一个我在开发 Deepin Control-Center 时,使用这个方法为 QListView 添加一个等待设备连接动画的示例,具体的 git 提交可以参考: 为 QListView 添加动画的示例