QProgressBar进度条,在修改了默认背景或进度条的颜色后,就没有了默认样式中加载高亮的动画效果,如果遇到后台耗时操作时,就会给用户以为软件卡住了没有进度。所以需要给进度条一个动画效果,表示操作仍在继续。
这里使用QTimeLine实现进度条的简单效果,主要是动态修改QProgressBar进度条控件的qss样式.
QProgressBar控件可以通过QSS修改样式,
主要使用QProgressBar {}
和QProgressBar::chunk{}
修改样式,
例如,要实现这种效果:
只需要给进度条添加一个渐进背景,如:
QProgressBar{
background: rgba(0, 0, 0, 50);
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 50);
border-radius: 12px;
}
QProgressBar::chunk
{
border-radius: 11px;
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 255, 255, 255), stop:1 rgba(219, 223, 255, 255));
}
或者实现这种效果:
修改样式:
QProgressBar{
background: rgba(0, 0, 0, 50);
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 50);
border-radius: 12px;
}
QProgressBar::chunk
{
border-radius: 11px;
background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(0, 0, 0, 255), stop:0.05 rgba(14, 8, 73, 255), stop:0.36 rgba(28, 17, 145, 255), stop:0.6 rgba(126, 14, 81, 255), stop:0.75 rgba(234, 11, 11, 255), stop:0.79 rgba(244, 70, 5, 255), stop:0.86 rgba(255, 136, 0, 255), stop:0.935 rgba(239, 236, 55, 255));
}
其他样式或控件属性可以参考以下文章:
当修改了默认样式后,如果遇到操作进度停留过久,就会让人觉得是内部操作卡住了,这个时候就需要有一个QProgressBar进度条默认高亮的动画效果,表示操作仍在继续。如:
就有个循环高亮的动画,不会让人觉得进度卡住了。
在这里主要使用QTimeLine时间轴来实现多种动画特效:
有时候不是所有的操作都能获取的一个具体的进度,像遍历文件列表这种,一开始也不知道有多少个文件,要实现一个进度条的效果,一般都是通过一个GIF图片循环播放来实现。
这里也可以使用QTimeLine时间轴来不停的修改QProgressBar进度条Value值,实现进度条不停的循环加载
像这种:
这种就是使用QTimeLine 设置5000毫秒内值从1到100的输出,再设置
setLoopCount(0)
不断循环;
- 代码示例:
//! 动态加载 --不停的循环加载
class Effect_Dynamic_Loading:public QObject
{
Q_OBJECT
public:
Effect_Dynamic_Loading(QProgressBar* _proBar,int ms=5000);
//! 是否开始动画效果
void IsStartAnimation(bool bol);
public slots:
//! 进度条的改变
void Bar_valueChanged(int value);
private:
//! 进度条控件
QProgressBar* proControl=nullptr;
//! 时间轴
QTimeLine* timeLine=nullptr;
};
Effect_Dynamic_Loading::Effect_Dynamic_Loading(QProgressBar* _proControl,int ms)
:proControl(_proControl)
{
//! 时间轴动画
timeLine = new QTimeLine(ms, _proControl); // 持续时间为5000ms
timeLine->setFrameRange(1, 100); // 动画的百分比范围
timeLine->setLoopCount(0);
timeLine->setCurveShape(QTimeLine::LinearCurve);
connect(timeLine, &QTimeLine::frameChanged, this, &Effect_Dynamic_Loading::Bar_valueChanged);
//! 绑定到动态属性 用于进度条的开启和关闭
proControl->setProperty("Dynamic",QVariant::fromValue(static_cast<Effect_Dynamic_Loading*>(this)));
}
void Effect_Dynamic_Loading::IsStartAnimation(bool bol)
{
if(bol)
timeLine->start();
else
{
timeLine->stop();
Bar_valueChanged(100);
}
}
//! 进度条的改变
void Effect_Dynamic_Loading::Bar_valueChanged(int value)
{
proControl->setValue(value);
proControl->update();
}
- 调用:
通过直接传入QProgressBar控件,绑定QTimeLine时间轴信号修改Value值,修改value值后记得刷新控件,否则在界面操作密集的时候会失去连续效果。
Effect_Dynamic_Loading* loading=new Effect_Dynamic_Loading(ui->progressBar);
loading->IsStartAnimation(true);
同时通过设置 Dynamic的动态属性,来控制进度条动画的开启关闭:
// 为了在其他控件或者方法中能控制加载开关
Effect_Dynamic_Loading* loadings= qvariant_cast<Effect_Dynamic_Loading*>(ui->progressBar_loopload->property("Dynamic"));
if(loadings!=NULL && loadings!=nullptr)
{
loadings->IsStartAnimation(true);
}
使用QTimeLine将一个切割线从进度条的开头移动到结尾的渐进背景,动态修改QProgressBar进度条的样式,由于是动态计算的距离,所以在移动过程中竖线会变宽,
同时设置当QProgressBar进度条达到最大值时自动停止动画特效。
- 代码示例:
//! 动态竖直线
//! 只要进度条不满百分百,就会一直加载特效
class Effect_Scale_Mark:public QObject
{
Q_OBJECT
public:
Effect_Scale_Mark(QProgressBar* _proControl);
public slots:
//! 动态样式
void updateValue(int frame);
//! 进度条的改变
//! 控制进度条的启动关闭
void Bar_valueChanged(int value);
private:
//! 进度条控件
QProgressBar* proControl=nullptr;
//! 时间轴
QTimeLine* timeLine=nullptr;
//! 是否被暂停
bool IsStartRun=false;
};
Effect_Scale_Mark::Effect_Scale_Mark(QProgressBar* _proControl)
:proControl(_proControl)
{
//! 进度条业务值改变
connect(_proControl, &QProgressBar::valueChanged, this, &Effect_Scale_Mark::Bar_valueChanged);
//! 时间轴动画
timeLine = new QTimeLine(2500, _proControl); // 持续时间为1000ms
timeLine->setFrameRange(1, 100); // 动画的百分比范围
timeLine->setLoopCount(0);
timeLine->setCurveShape(QTimeLine::LinearCurve);
connect(timeLine, &QTimeLine::frameChanged, this, &Effect_Scale_Mark::updateValue);
timeLine->start();
IsStartRun=true;
}
void Effect_Scale_Mark::updateValue(int frame)
{
// qDebug()<<"[frame] "<<frame;
double num=qMin((double)frame/100.0,1.0);
QString threshold=QString::number(qMin(num,1.0),'f',2);
QString threshold1=QString::number(qMin(num+0.01,1.0),'f',2);
QString threshold2=QString::number(qMin(num+0.02,1.0),'f',2);
// qDebug()<<"[threshold] "<<threshold<<" [threshold1] "<<threshold1<<" [threshold2] "<<threshold2;
QString DefaultStyle="QProgressBar{ "
"border: 0px;"
"background-color: #EAEAEA;"
"border-radius: 11px;"
"}"
"QProgressBar::chunk"
"{"
"border-radius: 11px;"
"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
" stop:0 rgba(240, 33, 33, 255),"
" stop:"+threshold+" rgba(240, 33, 33, 255), "
" stop:"+threshold1+" rgba(255, 255, 255, 255), "
" stop:"+threshold2+" rgba(236, 99, 76, 255), "
" stop:1 rgba(236, 99, 76, 255)); "
"}";
proControl->setStyleSheet(DefaultStyle);
}
void Effect_Scale_Mark::Bar_valueChanged(int value)
{
if(value==proControl->maximum())
{
if(IsStartRun)
{
timeLine->stop();
QString DefaultStyle="QProgressBar{ "
"border: 0px;"
"background-color: #EAEAEA;"
"border-radius: 11px;"
"}"
"QProgressBar::chunk"
"{"
"border-radius: 11px;"
"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,"
" stop:0 rgba(240, 33, 33, 255),"
" stop:1 rgba(236, 99, 76, 255)); "
"}";
proControl->setStyleSheet(DefaultStyle);
IsStartRun=false;
}
}
else
{
if(!IsStartRun)
{
timeLine->start();
IsStartRun=true;
}
}
}
- 调用:
每一个动画特效都是单个的QOBJECT对象,只需要在窗体初始化时声明对象就可以了。不需要重写QProgressBar控件。
Effect_Scale_Mark* mark=new Effect_Scale_Mark(ui->progressBar);
这个旋转进度条特效本质上也是QTimeLine时间轴不停循环了一个颜色的数组,
动态修改了QProgressBar进度条控件的样式:
- 代码示例:
//! 旋转样式特效
class Effect_Kaleidoscope:public QObject
{
Q_OBJECT
/*! 默认样式
QProgressBar{
background: rgba(0, 0, 0, 50);
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 50);
border-radius: 12px;
}
QProgressBar::chunk
{
border-radius: 11px;
background-color: qconicalgradient(cx:0, cy:0, angle:135,
stop:0 rgba(255, 255, 0, 69),
stop:0.375 rgba(255, 255, 0, 69),
stop:0.423533 rgba(251, 255, 0, 145),
stop:0.45 rgba(247, 255, 0, 208),
stop:0.477581 rgba(255, 244, 71, 130),
stop:0.518717 rgba(255, 218, 71, 130),
stop:0.55 rgba(255, 255, 0, 255),
stop:0.57754 rgba(255, 203, 0, 130),
stop:0.625 rgba(255, 255, 0, 69),
stop:1 rgba(255, 255, 0, 69));
}
*/
QStringList colorList;
public:
Effect_Kaleidoscope(QProgressBar* _proControl);
//! 动画效果的开关
void IsStartAnimation(bool bol);
public slots:
//! 动态样式
void updateValue(int frame);
private:
//! 进度条控件
QProgressBar* proControl=nullptr;
//! 时间轴
QTimeLine* timeLine=nullptr;
};
Effect_Kaleidoscope::Effect_Kaleidoscope(QProgressBar* _proControl)
:proControl(_proControl)
{
//! 时间轴动画
timeLine = new QTimeLine(500, _proControl); // 持续时间为1000ms
timeLine->setLoopCount(0);
timeLine->setCurveShape(QTimeLine::LinearCurve);
connect(timeLine, &QTimeLine::frameChanged, this, &Effect_Kaleidoscope::updateValue);
colorList<<"rgba(255, 255, 0, 69)";
colorList<<"rgba(251, 255, 0, 145)";
colorList<<"rgba(247, 255, 0, 208)";
colorList<<"rgba(255, 244, 71, 130)";
colorList<<"rgba(255, 218, 71, 130)";
colorList<<"rgba(255, 255, 0, 255)";
colorList<<"rgba(255, 203, 0, 130)";
colorList<<"rgba(255, 255, 0, 69)";
timeLine->setFrameRange(1, colorList.count()); // 动画的范围
}
void Effect_Kaleidoscope::IsStartAnimation(bool bol)
{
if(bol)
timeLine->start();
else
{
timeLine->stop();
}
}
void Effect_Kaleidoscope::updateValue(int frame)
{
int threshold_value=colorList.count();
int index=frame-1;
auto getV=[&](int& _index,int max)->int{
if(_index+1==max)
_index=0;
else
_index++;
return _index;
};
QString diffqss=" QProgressBar{ "
"background: rgba(0, 0, 0, 50);"
"border-radius: 4px;"
"border: 1px solid rgba(0, 0, 0, 50);"
"border-radius: 12px;"
"}"
"QProgressBar::chunk"
"{"
"border-radius: 11px;"
"background-color: qconicalgradient(cx:0, cy:0, angle:135,"
"stop:0 "+colorList[index]+","
"stop:0.375 "+colorList[index]+","
"stop:0.423533 "+colorList[getV(index,threshold_value)]+","
"stop:0.45 "+colorList[getV(index,threshold_value)]+","
"stop:0.477581 "+colorList[getV(index,threshold_value)]+","
"stop:0.518717 "+colorList[getV(index,threshold_value)]+","
"stop:0.55 "+colorList[getV(index,threshold_value)]+","
"stop:0.57754 "+colorList[getV(index,threshold_value)]+","
"stop:0.625 "+colorList[getV(index,threshold_value)]+","
"stop:1 "+colorList[index]+");"
"}";
proControl->setStyleSheet(diffqss);
proControl->update();
}
- 调用:
调用的同时,启动动画效果,这里也可以设置QProgressBar控件的动态属性来控制动画的开启关闭,只是这里没加。
Effect_Kaleidoscope* Kaleid=new Effect_Kaleidoscope(ui->progressBar_4);
Kaleid->IsStartAnimation(true);