Qt动态属性

本文详细介绍了Qt中如何自定义属性以及使用QPropertyAnimation进行动画操作。自定义属性可通过Q_PROPERTY宏定义,用于改变样式和动画效果。在样式表中,属性选择器可以结合自定义属性改变控件样式。在动画中,自定义属性配合QPropertyAnimation可以实现如透明度变化等效果。文中给出了具体的代码示例,包括按钮位置变化和标签透明度动画的实现。
摘要由CSDN通过智能技术生成

Qt的动态属性unpolish()和polish()

1. Qt中的属性

  • 属性是指窗口或控件的属性,比如opacity属性表示“透明度”,geometry指的是“位置和大小”,pos属性代表“位置”。qt中的控件有自带的属性,我们也可以自己定义属性。QObject这个类有一个函数setProperty,我们可以通过这个函数定义自己的属性,使用方法很简单,setProperty(const
    char * name, const QVariant &
    value),第一个参数是属性的名称,第二个参数是属性值。除了上面的方法,还有一种自定义属性的方法,就是在一个继承自QObject的类中使用 Q_PROPERTY 宏指令,简单用法如下:
    Q_PROPERTY(bool focus READ hasFocus) 
    Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
    Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged)

    Q_PROPERTY(参数类型 参数名称 READ 获得属性值函数 WRITE 设置属性值函数)
    比如Q_PROPERTY(bool bIsDoubi READ getDoubi WRITE setDoubi );
    其中,属性类型是bool类型,bIsDoubi是属性名称。除此之外还需要写两个函数,第一个是设置属性的函数void
    setDoui(bool),第二个是获得属性的函数bool getDoubi()。

  • 2. 自定义属性有什么作用

  • 目前所知的自定义属性有两个用途,第一是用于改变样式,第二是用于动画,下面分别作解释:
  • 1)改变样式

    翻开Qt助手,找到样式表语法部分,在通过选择器设置样式中有一个属性选择器,比如QPushButton[flat=“false”]意思就是当按钮属性flat为false时的样式。
    举个栗子,我们有个QWidget类,名字叫PropertyTest,界面中有一个按钮叫pushButton

#pushButton{border:4px solid blue;}
PropertyTest[borderColor="red"] #pushButton{border:4px solid red;}
 PropertyTest[borderColor="green"] #pushButton{border:4px solid green;}
 PropertyTest[borderColor="blue"] #pushButton{border:4px solid blue;}

按钮默认样式是blue蓝色,通过改变类PropertyTest的属性borderColor值改变按钮的颜色。
在代码中,首先定义属性

Q_PROPERTY(QString borderColor READ getBorderColor WRITE setBorderColor)

使用一个成员变量保存属性的值,并通过set和get函数分别设置和获得该值。

private:    
QString m_strBorderColor;
private:    
void setBorderColor(const QString &strBorderColor){ m_strBorderColor = strBorderColor; }   
QString getBorderColor(){ return m_strBorderColor; }

 单击按钮pushButton改变属性值,从而改变按钮pushButton的样式。

void PropertyTest::changeBorderColor()
{
    if (m_iTest % 3 == 0)    
    {        
    	setBorderColor("red");    
    }    
    else if (m_iTest % 3 == 1)   
     {        
     	setBorderColor("green");    
     }    
     else   
      {        
      	setBorderColor("blue");    
      }    
      style()->unpolish(ui.pushButton_3);    
      style()->polish(ui.pushButton_3);    
      update();    
      m_iTest++;
      }

最后要注意的是,上面代码中的unpolish和polish部分。
在Qt文档中有个提醒,在使用属性选择器时,如果之前控件有其它样式,那么需要重写设置一下,“旧的不去,新的不来”,通过unpolishpolish抹去旧的样式,涂上新的样式。

2)动画中使用自定义属性

  • 如果我们想通过动画使一个按钮逐渐变透明,思路会是这样:按钮QPushButton继承自QWidget,在QWidget中有个函数setWindowOpacity,所以只需使用动画类QPropertyAnimation,属性那个参数设置为windowOpacity。
    然而,实际中,按钮透明度不会有任何改变,继续查看文档才知道——只有调用setWindowFlags函数,将窗口属性设置为Qt::Window,windowOpacity这个属性才能生效。但是这样做pushbutton就不是正常的widget了。
    因此,有必要寻求其它方法,在QWidget中有一个函数setGraphicsEffect(QGraphicsEffect *),其中QGraphicsEffect有一个派生类QGraphicsOpacityEffect,可以通过它来设置QWidget的透明度
    m_pOpacityEffect = new QGraphicsOpacityEffect(this);
    m_pOpacityEffect->setOpacity(1);
    this->setGraphicsEffect(m_pOpacityEffect);
    
    Q_PROPERTY(qreal buttonOpacity READ buttonOpacity WRITE setBtnOpacity)

    上面的写法可能不太好,因为qreal精度与机器有关,最好用double或float。
    定义属性时,在函数setBtnOpacity中改变QGraphicsOpacityEffect对象,来调整透明度。
    好了,现在我们将动画属性名称设置为buttonOpacity—— QPropertyAnimation::setPropertyName(“buttonOpacity”) ,就能通过动画改变按钮的透明度了。

栗子

QPropertyAnimation类定义了Qt的属性动画。

QPropertyAnimation以Qt属性做差值,作为属性值存储在QVariants中,该类继承自QVariantAnimation,并支持基类相同的元类型动画。

声明属性的类必须是一个QObject,为了能够让属性可以用做动画效果,必须提供一个setter(这样,QPropertyAnimation才可以设置属性的值)。注意:这能够使它让许多Qt控件产生动画效果。

QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry");
animation->setDuration(10000);
animation->setStartValue(QRect(0, 0, 100, 30));
animation->setEndValue(QRect(250, 250, 100, 30));
 
animation->start();

首先,我们通过构造函数创建一个QPropertyAnimation对象,其中myWidget表示动画作用的QObject对象,geometry则表示QObject的属性。然后,可以指定属性的开始值和结束值。此过程等于在你自己的类中实现了自定义属性 - 需要用QVariantAnimation检测你自定义的QVariant类型是否支持。

QVariantAnimation类详细的描述了如何设置动画。需要注意的是:如果没有设置起始值,在QPropertyAnimation实例被创建时,属性就会设置起始值为它有的值。

QPropertyAnimation就其本身而言非常奏效。对于复杂的动画,例如:包含多个对象,则可以使用QAnimationGroup,动画组是一个可以包含其它动画的动画,并可以管理动画的播放。可以参考QParallelAnimationGroup的示例。

1、原始属性

利用上面讲解的geometry属性,来实现一个动画坐标变化。

这里写图片描述

 


QPropertyAnimation *pAnimation = new QPropertyAnimation(m_pLabel, "geometry");
pAnimation->setDuration(1000);
pAnimation->setStartValue(QRect(0, 0, 75, 25));
pAnimation->setEndValue(QRect(200, 130, 75, 25));
pAnimation->setEasingCurve(QEasingCurve::OutBounce);  // 缓和曲线风格
connect(pStartButton, SIGNAL(clicked(bool)), pAnimation, SLOT(start()));

2、自定义属性

通过自定义属性alpha,来使用动画设置标签的样式。

这里写图片描述

 

#ifndef MAIN_WINDOW_H
#define MAIN_WINDOW_H
 
...
 
class MainWindow : public CustomWindow
{
    Q_OBJECT
    Q_PROPERTY(int alpha READ alpha WRITE setAlpha)
 
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
 
private:
    int alpha() const;
    void setAlpha(const int alpha);
 
private:
    int m_nAlpha;
    QLabel *m_pLabel;
};
 
#endif // MAIN_WINDOW_H
#include "main_window.h"
 
MainWindow::MainWindow(QWidget *parent)
    : CustomWindow(parent)
{
    ...
 
    QPushButton *pStartButton = new QPushButton(this);
    pStartButton->setText(QString::fromLocal8Bit("开始动画"));
 
    m_pLabel = new QLabel(this);
    m_pLabel->setText(QString::fromLocal8Bit("一去丶二三里"));
    m_pLabel->setAlignment(Qt::AlignCenter);
    m_pLabel->setStyleSheet("color: rgb(0, 160, 230);");
 
    QPropertyAnimation *pAnimation = new QPropertyAnimation();
    pAnimation->setTargetObject(this);
    pAnimation->setPropertyName("alpha");
    pAnimation->setDuration(1000);
    pAnimation->setKeyValueAt(0, 255);
    pAnimation->setKeyValueAt(0.5, 100);
    pAnimation->setKeyValueAt(1, 255);
    pAnimation->setLoopCount(-1);  //永远运行,直到stop
    connect(pStartButton, SIGNAL(clicked(bool)), pAnimation, SLOT(start()));
 
    ...
}
 
int MainWindow::alpha() const
{
    return m_nAlpha;
}
 
void MainWindow::setAlpha(const int alpha)
{
    m_nAlpha = alpha;
    QString strQSS = QString("color: rgb(0, 160, 230); background-color: rgba(10, 160, 105, %1);").arg(m_nAlpha);
    m_pLabel->setStyleSheet(strQSS);
}

 Qt qss 动态属性

QFrame#frmPreImg[selected=false]{
    border:none;
    background-color:#D8DFEA;
}
QFrame#frmPreImg[selected=true]{
    border:4px solid #32CD32;
    background-color:#D8DFEA;
}
m_frmPreImg1->setProperty("selected",true);
      m_frmPreImg1->style()->unpolish(m_frmPreImg1);
      m_frmPreImg1->style()->polish(m_frmPreImg1);

      m_frmPreImg1->update();

参考

  1. Qt之动态属性unpolish()和polish()
  2. Qt 之 QPropertyAnimation_青春不老,奋斗不止!-CSDN博客_qpropertyanimation
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值