简述
记录和分享自己写的一个倒计时小控件。通过自定义QLabel控件,重写painter事件来绘制一个倒计时控件。
一、运行效果
运行程序,初始化一个时间。点击开始后,开始倒计时,外层圆形进度条慢慢缩减。
二、上代码
mylabel.h
代码如下(示例):
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QObject>
#include <QLabel>
#include <QPainter>
class MyLabel : public QLabel
{
Q_OBJECT
public:
MyLabel(QWidget *parent = Q_NULLPTR);
~MyLabel();
public:
//计时器更新 倒计时
void setTime(double second);
signals:
public slots:
protected:
void paintEvent(QPaintEvent *);
virtual bool event(QEvent *e);
private:
void drawTimer(QPainter *);//画计时器
private:
double m_time;//倒计时时间
};
#endif // MYLABEL_H
mylabel.cpp
代码如下(示例):
#include "mylabel.h"
#include<QDebug>
#pragma execution_character_set("utf-8")
MyLabel::MyLabel(QWidget *parent)
:QLabel (parent)
{
}
MyLabel::~MyLabel()
{
}
void MyLabel::setTime(double second)
{
m_time = second;
update();
}
//重写paint事件
void MyLabel::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e);
QPainter painter(this);
//设置抗锯齿
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
drawTimer(&painter);
}
bool MyLabel::event(QEvent *e)
{
return QLabel::event(e);
}
void MyLabel::drawTimer(QPainter *p)
{
//先设置外矩形的大小用于绘制圆形进度条
QRect rcOut = this->rect();
//adjust四个参数:dx1,dy1相对于左上角的点,dx2,dy2相对于右下角的点
rcOut.adjust(10,10,-10,-10);
QSize outSize = rcOut.size();
//获取这个矩形的左上角坐标
int out_X = rcOut.x();
int out_Y = rcOut.y();
//设置内矩形的大小用于绘制时间
QRect rcInt = this->rect();
rcInt.adjust(20,90,-20,-90);
QSize inSize = rcInt.size();
int in_X = rcInt.x();
int in_Y = rcInt.y();
//画内矩形
//画矩形边框色,同主界面的背景色,不同的话会有出现一个长方形矩形
p->setPen(QPen(QColor(68,85,123), 1, Qt::SolidLine));
//绘制矩形
p->drawRect(rcInt);
//绘制时间
//设置画笔样式
QFont font;
//大小根据主界面label的大小调整
font.setPointSize(45);
p->setFont(font);
QPen pen;
pen.setColor(QColor("#ffffff"));
pen.setWidth(1);
pen.setStyle(Qt::SolidLine);
p->setPen(pen);
QString timer;
if(m_time == 0)
{
timer = "00:00";
//绘制文字,用内矩形的size,文字居中
p->drawText(in_X,in_Y,inSize.width(),inSize.height(),Qt::AlignVCenter |Qt::AlignHCenter,timer);
}
else {
int time = m_time/100+1; //加1是因为小于100时就是0了,但是绘制还未结束
timer = "00:" + QString::number(time);
if(time < 10)
{
timer = "00:0" + QString::number(time);
}
p->drawText(in_X,in_Y,inSize.width(),inSize.height(),Qt::AlignVCenter |Qt::AlignHCenter,timer);
}
//绘制圆形进度条
//QLinearGradient 参数:渐变的开始坐标,渐变的结束坐标
QLinearGradient gradient(out_X, out_Y, outSize.height(), out_Y);//左右渐变
//QLinearGradient gradient(out_X, out_Y, out_X, outSize.height()+out_Y);//上下渐变
gradient.setColorAt(0, QColor("#E3521B"));
gradient.setColorAt(1.0, QColor("#8BE31B"));
int startAngle = 90*16; //开始的角度,0度在图形的最左侧
int spanAngle = m_time/8000*(-360*16); //覆盖的角度
QPen penForeground;
penForeground.setBrush(gradient);
penForeground.setWidth(15);
penForeground.setJoinStyle(Qt::RoundJoin);
penForeground.setCapStyle(Qt::RoundCap);
p->setPen(penForeground);
//绘制圆环,用到外圈的size
p->drawArc(rcOut, startAngle, spanAngle);
}
TimerWidget.h
#ifndef TIMERWIDGET_H
#define TIMERWIDGET_H
#include <QWidget>
class QTimer;
namespace Ui {
class TimerWidget;
}
class TimerWidget : public QWidget
{
Q_OBJECT
public:
explicit TimerWidget(QWidget *parent = nullptr);
~TimerWidget();
//初始化
void initForm();
private slots:
void on_m_startBtn_clicked();
void timeEnd();
private:
Ui::TimerWidget *ui;
double m_time;//时间
QTimer *m_timer;//定时器,用于给计时器发送时间
};
#endif // TIMERWIDGET_H
TimerWidget.cpp
#include "TimerWidget.h"
#include "ui_TimerWidget.h"
#include <QTimer>
TimerWidget::TimerWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::TimerWidget)
{
ui->setupUi(this);
initForm();
connect(m_timer,&QTimer::timeout,this,&TimerWidget::timeEnd);
}
TimerWidget::~TimerWidget()
{
delete ui;
}
//初始化
void TimerWidget::initForm()
{
//设置背景色,qss
QString strStyle = "QWidget#TimerWidget{background-color:rgb(68,85,123);}";
setStyleSheet(strStyle);
setFixedSize(300,300);
ui->m_timer->setFixedSize(250,250);
ui->m_startBtn->setText("开始");
m_timer = new QTimer(this);
m_time = 7999;
ui->m_timer->setTime(m_time);
}
//开始
void TimerWidget::on_m_startBtn_clicked()
{
//每10毫秒执行一次
//每10毫秒刷新一次为了让进度条更流畅
m_timer->start(10);
}
void TimerWidget::timeEnd()
{
//如果小于0停止计时
if(m_time < 0)
{
m_timer->stop();
return;
}
ui->m_timer->setTime(m_time);
m_time --;
}
TimerWidget ui设计
添加一个开始按钮和一个QLabel,QLabel需要提升为mylabel,控件的提升不会的站里很多例子。
main.cpp
#include "TimerWidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TimerWidget w;
w.show();
return a.exec();
}
总结
第一次写,有很多不足之处,分享一下互相学习。
程序目的主要是实现一个圆形的进度条,带有渐变色和时间。