Qt实现数字滚动动画效果
自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:
https://www.cnblogs.com/bclshuai/p/11380657.html
1.1 Qt实现数字滚动动画效果
1.1.1 应用场景说明
如下图所示,需要显示人脸检测的数量,变动画的方式实现个位数字滚动,个位由9变成0时,十位也要滚动,实现进位。当个位十位都是9时,数字不在增加,而是显示加号+。
1.1.2 实现方法
实现方案,个位十位都有上下两个label显示数字。通过QPropertyAnimation属性动画控制两个label位置同时向上。动画结束后,再将两个label还原到原始位置。在还原位置之前,先前上面的labelnum值设置为下面labelnum1的值,下面labelnum1的值设置为+1后的值,避免出现数字闪现变小的问题。
头文件实现
#ifndef NUMSHOWWIDGET_H
#define NUMSHOWWIDGET_H
#include <QPropertyAnimation>
#include<QParallelAnimationGroup>
#include <QSequentialAnimationGroup>
#include <QWidget>
#include"ui_NumShowWidget.h"
#include<QMutex>
#include<QWaitCondition>
#include<QTimer>
class NumShowWidget : public QWidget
{
Q_OBJECT
public:
NumShowWidget();
~NumShowWidget();
void initNum();//个位十位上下初始化0,1值
/*
设置为某个值,会根据数字增量的大小增加数字值,根据time求出平均动画时间步长。增量大时速度快,增量小时速度慢
*/
void setNum(int num,int time);
void addNum(int num, int time);
public slots:
void SlotTimeAddNum();
int getNum();
void pushNum(int num);
private:
Ui::NumShowWidget ui;
int m_tenwei = 0;//十位
int m_gewei = 0;//个位
QLabel* m_tenCurrent = NULL;//十位当前label
QLabel* m_tenDown=NULL;//十位下面的label
QLabel* m_geCurrent = NULL;//个位当前label
QLabel* m_geDown = NULL;//个位下面的label
int m_count = 0;//动画执行的次数,增量为10,则执行十次上滚动画
int m_num=0;//保存当前显示的数字。
QParallelAnimationGroup* tenAnimation;
QMutex m_mutex;
QWaitCondition m_FinishAnimation;
QTimer m_checktime;
QMutex m_addNumMutex;
QVector<int> m_vectNum;
bool m_bFinishAni=true;//避免第一次动画未执行结束,第二次动画就开始,会错乱,所加上一个判断条件。
QPropertyAnimation * tenCurrent =NULL;
QPropertyAnimation * tenDown = NULL;
};
#endif // NUMSHOWWIDGET_H
源文件实现
#include "NumShowWidget.h"
#include"hlog1.h"
#include<QFontDatabase>
NumShowWidget::NumShowWidget()
{
ui.setupUi(this);
setWindowModality(Qt::NonModal);
setWindowFlags(Qt::FramelessWindowHint);
this->resize(32, 32);
m_tenCurrent = ui.labelten;
m_tenDown = ui.labelten1;
m_geCurrent = ui.labelnum;
m_geDown = ui.labelnum1;
m_tenCurrent->setText("0");
m_tenDown->setText("1");
m_geCurrent->setText("0");
m_geDown->setText("1");
ui.labelplus->hide();
tenAnimation = new QParallelAnimationGroup(this);
tenCurrent = new QPropertyAnimation(m_tenCurrent, "geometry");
tenCurrent->setDuration(100);
tenCurrent->setStartValue(QRect(4, 0, 12, 32));
tenCurrent->setEndValue(QRect(4, -32, 12, 32));
tenAnimation->addAnimation(tenCurrent);
tenDown = new QPropertyAnimation(m_tenDown, "geometry");
tenDown->setDuration(100);
tenDown->setStartValue(QRect(4, 32, 12, 32));
tenDown->setEndValue(QRect(4, 0, 12, 32));
tenAnimation->addAnimation(tenDown);
connect(tenAnimation, &QAbstractAnimation::finished, this, [=]() {
m_tenCurrent->setText(QString::number(m_tenwei++));
m_tenCurrent->setGeometry(4, 0, 12, 32);
m_tenCurrent->raise();
m_tenDown->setGeometry(4, 32, 12, 32);
m_tenDown->setText(QString::number((m_tenwei + 1)));
});
m_checktime.setInterval(1000);
connect(&m_checktime, &QTimer::timeout, this, &NumShowWidget::SlotTimeAddNum);
m_checktime.start();
}
NumShowWidget::~NumShowWidget()
{
if (tenAnimation != NULL)
{
delete tenAnimation;
tenAnimation = NULL;
}
}
void NumShowWidget::initNum()
{
m_tenwei = 1;
m_gewei = 1;
m_num = 0;
m_tenCurrent->setText("0");
m_tenCurrent->setGeometry(QRect(4, 0, 12, 32));
m_tenDown->setText("1");
m_tenDown->setGeometry(QRect(4, 32, 12, 32));
m_geCurrent->setText("0");
m_geDown->setText("1");
m_geCurrent->setGeometry(QRect(15, 0, 12, 32));
m_geDown->setGeometry(QRect(15, 32, 12, 32));
ui.labelplus->hide();
m_vectNum.clear();
m_bFinishAni = true;
}
void NumShowWidget::setNum(int num, int time)
{
if (ui.labelplus->isVisible())
{
return;
}
m_num = ui.labelten->text().toInt()*10+ui.labelnum->text().toInt();
if (num <= m_num)//值没有变
{
m_mutex.lock();
m_bFinishAni = true;
m_mutex.unlock();
return;
}
addNum(num - m_num, time);
}
void NumShowWidget::addNum(int num, int time)
{
if (num <= 0)
{
return;
}
LOG_INFO("NUCOUNT LOCK");
int steptime = time / num;//动画时间步长
tenCurrent->setDuration(steptime);
tenDown->setDuration(steptime);
m_count = num;
QParallelAnimationGroup* paraAnimation = new QParallelAnimationGroup(this);
QPropertyAnimation * geCurrent = new QPropertyAnimation(m_geCurrent, "geometry");
geCurrent->setDuration(steptime);
geCurrent->setStartValue(QRect(15, 0, 12, 32));
geCurrent->setEndValue(QRect(15, -32, 12, 32));
paraAnimation->addAnimation(geCurrent);
QPropertyAnimation *geDown = new QPropertyAnimation(m_geDown, "geometry");
geDown->setDuration(steptime);
geDown->setStartValue(QRect(15, 32, 12, 32));
geDown->setEndValue(QRect(15, 0, 12, 32));
paraAnimation->addAnimation(geDown);
paraAnimation->start();
connect(paraAnimation, &QAbstractAnimation::finished, this, [=]() {
m_count--;
m_geCurrent->setText(QString::number(m_gewei++));
m_geCurrent->setGeometry(15, 0, 12, 32);
m_geCurrent->raise();
m_geDown->setGeometry(15, 32, 12, 32);
if (m_gewei >= 10)
{
if (m_tenwei < 10)
{
tenAnimation->start();
}
else
{
ui.labelplus->show();
m_mutex.lock();
m_bFinishAni = true;
m_mutex.unlock();
delete paraAnimation;
LOG_INFO("NUCOUNT ULOCK");
return;
}
m_gewei = 0;
}
m_geDown->setText(QString::number((m_gewei) % 10));
if (m_count > 0)
{
paraAnimation->start();
}
else
{
m_mutex.lock();
m_bFinishAni = true;
m_mutex.unlock();
delete paraAnimation;
LOG_INFO("NUCOUNT ULOCK");
}
})
}
void NumShowWidget::SlotTimeAddNum()
{
if (m_bFinishAni)
{
int num = getNum();
if (num > 0)
{
m_mutex.lock();
m_bFinishAni = false;
m_mutex.unlock();
setNum(num, 1000);
}
}
}
int NumShowWidget::getNum()
{
m_addNumMutex.lock();
if (m_vectNum.size() > 0)
{
int num = m_vectNum.front();
m_vectNum.pop_front();
m_addNumMutex.unlock();
return num;
}
else
{
m_addNumMutex.unlock();
return -1;
}
}
void NumShowWidget::pushNum(int num)
{
m_addNumMutex.lock();
m_vectNum.push_back(num);
m_addNumMutex.unlock();
}