# QT自定义控件 **Repository Path**: fengdaokanhai/qt-custom-control ## Basic Information - **Project Name**: QT自定义控件 - **Description**: QT自定义控件 - **Primary Language**: C++ - **License**: MulanPSL-2.0 - **Default Branch**: develop - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-12-19 - **Last Updated**: 2023-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### QT自定义控件 在介绍自定义控件之前,我先介绍一下QPropertyAnimation的使用方法。后面,会用到这个类。 ### 1 QT 动画 QPropertyAnimation #### 1.1 QT 动画简述 --- Qt动画架构中的主要类如下图所示: ![img](http://hiphotos.baidu.com/exp/pic/item/54baacfb43166d22f0357962442309f79152d243.jpg) 动画框架由基类QAbstractAnimation和它的两个儿子QVariantAnimation和QAnimationGroup组成。QAbstractAnimation是所有动画类的祖宗。它包含了所有动画的基本属性。比如开始,停止和暂停一个动画的能力。它也可以接收时间改变通知。 动画框架又进一步提供了QProertyAnimation类。它继承自QVariantAnimation并对某个Qt属性执行动画。此类对属性执行一个宽松曲线插值。所以当你想去动画一个值时,你可以把它声明为一个属性,并且让你的类成为一个QObject。这给予我们极大的自由度来动画那些已存在的widget和其它QObject。 复杂的动画可以通过建立一个QAbstractAnimation的树来构建。这个树通过使用QAnimationGroups来创建,QAnimationGroups作为其它动画的容器。注意动画组也是从QAbstractAnimation派生的,所以动画组可以再包含其它动画组。 动画框架可以单独使用,同时也被设计为状态机框架的一部分。状态机提供了一个特定的状态可以用来播放动画。在进入或退出某个状态时QState也可以设置属性们,并且这个特定的动画状态将在指定QPropertyAnimation时给予的值之间做插值运算。后面我们要进一步介绍此问题。 在场景的背后,动画被一个全局定时器收集,这个定时器发送update到所有的正在播放的动画中。 #### 1.2 **QPropertyAnimation** --- QPropertyAnimation类定义了Qt的属性动画。 QPropertyAnimation以Qt属性做差值,作为属性值存储在QVariants中,该类继承自QVariantAnimation,并支持基类相同的元类型动画。 声明属性的类必须是一个QObject,为了能够让属性可以用做动画效果,必须提供一个setter(这样,QPropertyAnimation才可以设置属性的值)。注意:这能够使它让许多Qt控件产生动画效果。 首先,我们通过构造函数创建一个QPropertyAnimation对象,其中myWidget表示动画作用的QObject对象,geometry则表示QObject的属性。然后,可以指定属性的开始值和结束值。此过程等于在你自己的类中实现了自定义属性 - 需要用QVariantAnimation检测你自定义的QVariant类型是否支持。 QVariantAnimation类详细的描述了如何设置动画。需要注意的是:如果没有设置起始值,在QPropertyAnimation实例被创建时,属性就会设置起始值为它有的值。 QPropertyAnimation就其本身而言非常奏效。对于复杂的动画,例如:包含多个对象,则可以使用QAnimationGroup,动画组是一个可以包含其它动画的动画,并可以管理动画的播放。可以参考QParallelAnimationGroup的示例。 ##### 公共函数 --- - QByteArray propertyName() const 返回动画的目标属性名 - void setPropertyName(const QByteArray & propertyName) 设置动画的目标属性名 - void setTargetObject(QObject * target) 设置动画作用的QObject对象 - QObject * targetObject() const 返回动画作用的QObject对象 ##### **代码01:** --- ```C++ QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry"); animation->setDuration(10000); //设置时间10s animation->setStartValue(QRect(0, 0, 0, 0)); //动画开始位置和大小 animation->setEndValue(QRect(250, 250, 100, 30));//动画结束位置和大小 animation->start(); ``` img 上面的例子举在开始值和结束值之间做线性插值。还可以在开始和结束值之间设置值,插值运算就会经过这些点。 **代码02:** --- ```C++ QPropertyAnimation *animation1 = new QPropertyAnimation(ui.pushButton, "geometry"); animation1->setDuration(10000); animation1->setKeyValueAt(0, QRect(0, 0, 00, 00)); animation1->setKeyValueAt(0.4, QRect(20, 250, 20, 30)); animation1->setKeyValueAt(0.8, QRect(100, 250, 20, 30)); animation1->setKeyValueAt(1, QRect(250, 250, 100, 30)); animation1->setEndValue(QRect(250, 250, 100, 30)); animation1->start(); ``` ![img](http://hiphotos.baidu.com/exp/pic/item/d1571724ab18972bb3e36c3ce4cd7b899f510a2f.jpg) 移位是在这些点中间以线性插值进行的。 宽松曲线 `animation1->setEasingCurve(QEasingCurve::OutBounce); ` QPropertyAnimation在属性的开始值和结束值之间执行一个插值运算。除了向动画添加更多的关键值外,你还可以使用一个宽松曲线。宽松曲线描述了一个在0和1之间插值的速度变化的函数,如果你想控制一个动画的速度而不改变插值的路径时,就非常有用。 这里,动画将按照一个曲线进行,这个曲线使得动画像一个跳动的皮球从开始位置跳到结束位置。QEasingCurve具有一个大曲线集合,你可以从里面选择一个。它们被定义为QEasingCurve::Type枚举。如果你需要不一样的曲线,你也可以自己实现一个,然后注册到QEasingCurve。 ### 2 自定义控件实例 展示效果图: ![](https://s4.ax1x.com/2021/12/22/T19mSH.gif) 鼠标进入图标后会有放大效果。 添加四个widget ![](https://s4.ax1x.com/2021/12/22/T1Kylt.png) 然后提升窗口部件 ![](https://s4.ax1x.com/2021/12/22/T1KsSI.png) ```C++ enterAnimation = new QPropertyAnimation(this, ""); enterAnimation->setStartValue(0); enterAnimation->setEndValue(5); enterAnimation->setDuration(200); connect(enterAnimation, SIGNAL(valueChanged(QVariant)), this, SLOT(enterImageChanged(QVariant))); ``` ```C++ void AnimationButton::enterImageChanged(QVariant index) { int i = index.toInt(); targetWidth = pixWidth + i * 5; targetHeight = pixHeight + i * 5; update(); } ``` ```C++ void AnimationButton::enterEvent(QEvent *) { enter = true; leave = false; pixWidth = pixWidth - 25; pixHeight = pixHeight - 25; enterAnimation->start(); } ``` 鼠标进入进入四个widget区域,启动`enterAnimation` . [源代码下载](https://gitee.com/brucelite/qt-custom-control)