Qt动画框架-(2)Qt动画和属性

来源:互联网 发布:巨人网络股票代码 编辑:程序博客网 时间:2024/06/16 05:39

Qt动画和Qt类属性

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<QGridLayout*>(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属性

您还可以为未声明为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);

实现效果
这里写图片描述
图3 曲线动画

通过设置QEasingCurve可以实现很多不同的效果
这里写图片描述
详细需要查看文档,总大概40多个 ==