QPropertyAnimation类可以在Qt属性中进行插值。
属性值一般是类中的get/set方法,或者直接查看源码:
//QWidget的属性(一部分)
Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry)
Q_PROPERTY(QRect frameGeometry READ frameGeometry)
Q_PROPERTY(QRect normalGeometry READ normalGeometry)
Q_PROPERTY(int x READ x)
Q_PROPERTY(int y READ y)
通常这个类应该用于动画直接设置值,事实上,它的父类QVariantAnimation,有一个updateCurrentValue()的空实现,除非我们在valuechange的信号上改变它,否则它不会改变任何值。
我们选择让Qt属性动起来的一个主要原因是它为我们提供了在Qt API中激活现有类的自由。值得注意的是,QWidget类(我们也可以嵌入到QGraphicsView中)有其边界、颜色等属性。
Widget w;
QLabel pix;
pix.setPixmap(QPixmap("E:/pic/poi2.jpg"));
pix.setParent(&w);
w.addItem(&pix);
w.show();
QPropertyAnimation animation(&w, "geometry");
animation.setDuration(2000);
QDesktopWidget desktop;
animation.setStartValue(QRect(desktop.width() / 2,
desktop.height() / 2,
pix.width(),
pix.height()));
animation.setEndValue(QRect(desktop.width() / 2,
0,
pix.width(),
pix.height()));
animation.start();
其中Widget继承自QWidget,addItem实现如下(下文的addItem也是此函数)
void addItem(QWidget *item)
{
if(item == nullptr)
{
return;
}
if(layout() == nullptr)
{
QGridLayout* l = new QGridLayout;
l->addWidget(item);
setLayout(l);
}
else
{
QGridLayout* l = static_cast(layout());
l->addWidget(item);
}
}
该动画的效果
图1 动画示例
动画解释:从屏幕中心(desktop.width() / 2,desktop.height() / 2)上升到屏幕最上方(QRect(desktop.width() / 2,0)时间总长度为2s(animation.setDuration(2000))。
上面的例子将在开始值和结束值之间进行线性插值。还可以设置位于开始和结束值之间的值。插值就会被这些点所利用。
更改部分代码
animation.setKeyValueAt(0, QRect(desktop.width() / 2,
desktop.height() / 2,
pix.width(),
pix.height()));
animation.setKeyValueAt(0.7, QRect(desktop.width() / 2,
0,
pix.width(),
pix.height()));
animation.setKeyValueAt(1, QRect(desktop.width() / 2,
desktop.height() / 2,
pix.width(),
pix.height()));
animation.start();
该动画效果
图2 插值动画
动画解释:从屏幕中心上升到屏幕最上方,然后回到出发点,各比例setKeyValueAt的第一个参数时间总长度为2s。
您还可以为未声明为Qt属性的QObject的值生成动画。唯一的要求是这个值有一个setter。然后,您可以对包含该值的类进行子类化,并声明使用此setter的属性。请注意,每个Qt属性都需要一个getter,所以如果没有定义,您将需要自己提供一个getter。
class MyGraphicsRectItem : public QObject, public QGraphicsRectItem
{
Q_OBJECT
Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
};
在上面的代码示例中,我们子类QGraphicsRectItem并定义几何属性。即使QGraphicsRectItem不提供几何属性,我们现在也可以对窗口小部件的几何图形进行动画处理。(关于Qt属性的章节将在后期更新)
当您想要动画QGraphicsItem时,您也可以使用QPropertyAnimation。但是,QGraphicsItem不会继承QObject。一个很好的解决方案是将您想要动画化的图形项子化。这个类也会继承QObject。这样,QPropertyAnimation可以用于QGraphicsItem。下面的例子显示了如何完成。另一种方法是继承QGraphicsWidget,它已经是一个QObject。
class Pixmap : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
...
特别注意,QObject必须是元元对象系统要求的第一个类。
如前所述,QPropertyAnimation在开始和结束属性值之间执行插值。除了为动画添加更多的键值之外,您还可以使用缓动曲线。缓和曲线描述了一种控制0和1之间内插速度的函数的功能,如果要在不改变插值路径的情况下控制动画速度,则该方法很好用。
在第一个线性插值动画代码中添加一句即可
animation.setEasingCurve(QEasingCurve::OutBounce);