LoadingWidget
加载动画一般是UI出图,使用GIF进行播放,这样子虽然快速而且简单便捷,但是很难和代码产生更多交互,当然,把每一帧图片逐帧控制播放也是可以的,只是很难对代码做到复用,在其它项目中如果需要使用的话,很难根据需要去做更改,往往需要UI重新制作。因此想制作一个可复用的加载控件。当然,主要还是我看到Windwos10的加载动画觉得很不错,想自己实现一下放到自己的项目中
实现思路
实际上,作为动画,它的显示必然是一帧一帧地显示在电脑屏幕上的,只不过我们用代码控制的时候,不是使用贴图,而是通过我们计算去算出每一帧我们要如何绘制,然后通过时间更新每一帧要绘制的内容。
为了写代码的时候使得我们的对象有良好的复用性,方便通过继承实现更多的扩展,我们需要了解到我们在实现加载动画的时候需要怎么一步步计算到每一帧绘制需要用到的数据。
下面是一个简单的加载动画
首先,既然动画是一帧一帧地绘制得到的,那么对于帧序列来说我们需要三个东西
- 动画时长
- 计时器
- 每一帧需要的数据
动画时长就是完成一次动画需要的时间,这个时间,计时器用于更新图画,比如我要30ms更新一帧,那么计时器每隔30ms就应该调用我的绘制函数去进行绘制。第一帧绘制第一个心型为较深的灰色,那么30s后第二帧就应该调用绘制函数绘制每二个心形为较深的灰色,第一个相应地绘制比较浅一些。至于每一帧需要的数据,和上面加载动画对应,就是绘制每一个心形的位置和大小,也就是把心形包含起来的矩形对应的位置大小。
其次,我们希望继承者能有更多的实现,那么基类就只需要最基本的实现,并且为更多的扩展提供接口。
基类与派生类
就如上面所说一样,动画总是避免不了动画时长、刷新时间、进度数据,绘制数据等,那么我们将这些需要的数据封装起来,并且提供给派生类,由派生类根据这些数据去实现具体每一帧的显示。但是由于不同的动画需要进行的绘制数据是不同的,因此我们只是将数据保留在基类中,然后由派生类设定具体每帧中的绘制数据是什么。
那么基类的类定义如下
class BaseLoadingWidget : public QWidget
{
Q_OBJECT
public:
explicit BaseLoadingWidget(QWidget *parent = nullptr);
void setEasingCurve(const QEasingCurve& curve); // 设置插值器
void setFrameRate(const int& frameRate); // 设置帧率
void setDuration(const int& duration); // 设置动画时长
void setExtendDuration(c