文章目录
- 1、电池控件效果
- 2、自定义电池控件的实现
- 2.1、初始化电池控件的基本属性
- 2.2、电池控件电量的增减变化的实现
- 2.3、绘制电池控件的边框和头部
- 2.4、绘制电池控件内部背景
- 2.5、绘制电池电量的文本
- 3、完整代码
1、电池控件效果
使用QPainter来进行绘制自定义的控件,然后通过QTimer来实现电池控件的电量变化效果,效果图如下:
2、自定义电池控件的实现
2.1、初始化电池控件的基本属性
在设计电池控件时,首先得考虑这个控件的基本属性,然后通过自定义一个初始化的接口或者通过初始化列表来初始化电池控件的属性,如下是自定义初始化接口来初始化电池控件的基本属性:
void Widget::init()
{
m_margin=5;
m_isForward=true;
m_currentValue=10;
m_maxValue=100;
m_minValue=0;
m_batteryWidth=150;
m_batteryHeight=60;
}
下图是私有作用域下的电池属性:
2.2、电池控件电量的增减变化的实现
要想实现电池控件电量增减变化,必须使用QTimer来构造一个定时器,设置定时器的周期,然后是通过信号槽绑定,让窗口上的电池控件不断触发改变电量的槽函数,最后是使用update()来实现窗体的重绘。
void Widget::changeValue()
{
if(m_isForward)
{
m_currentValue+=1;
}
else
{
m_currentValue-=1;
}
if(m_currentValue>=100)
{
m_currentValue=100;
m_isForward=false;
}
if(m_currentValue<=0)
{
m_currentValue=0;
m_isForward=true;
}
update();
}
2.3、绘制电池控件的边框和头部
绘制电池控件边框时,将电池的主体部分绘制到窗体中心,然后是绘制电池控件的头部,绘制头部时就是绘制一条线段,只是这条线段比较粗,代码如下:
void Widget::drawBorder(QPainter *painter)
{
//保存画家的当前状态
painter->save();
//设置画笔
painter->setPen(QPen(Qt::gray,8));
//无画刷
painter->setBrush(Qt::NoBrush);
//电池主体居中
m_batteryRect=QRectF((this->width()-m_batteryWidth)/2,(this->height()-m_batteryHeight)/2,
m_batteryWidth,m_batteryHeight);
//绘制电池边框
painter->drawRoundRect(m_batteryRect,15,15);
//绘制电池头部
painter->setPen(QPen(Qt::gray,12));
QLine line(m_batteryRect.topRight().x()+10,m_batteryRect.topRight().y()+10,
m_batteryRect.bottomRight().x()+10,m_batteryRect.bottomRight().y()-10);
painter->drawLine(line);
//恢复画家保存的状态
painter->restore();
}
效果图如下:
2.4、绘制电池控件内部背景
绘制电池控件内部背景时,首先得考虑电池的电量在什么电量该用什么画刷来填充颜色,其次是确认电池控件内部背景的圆角矩形的左上角和右下角坐标。
void Widget::drawBackground(QPainter *painter)
{
//保存画家的当前状态
painter->save();
//确认画刷颜色
if(m_currentValue<=10)
{
//红色
painter->setBrush(QBrush(QColor(204,38,38)));
}
else if(m_currentValue<=20)
{
//橙色
painter->setBrush(QBrush(QColor(190,163,0)));
}
else
{
//绿色
painter->setBrush(QBrush(QColor(50,205,51)));
}
//将电量转化为宽度
double w=m_currentValue*(m_batteryRect.width()-(m_margin*2))/100;
//确认左上角位置
QPointF topLeft=QPointF(m_batteryRect.topLeft().x()+m_margin,m_batteryRect.topLeft().y()+m_margin);
//确认右下角位置
QPointF bottomRight=QPointF(m_batteryRect.topLeft().x()+w+m_margin,m_batteryRect.bottomRight().y()-m_margin);
//绘制电量背景
painter->setPen(Qt::NoPen);
QRectF rectF(topLeft,bottomRight);
painter->drawRoundRect(rectF,10,10);
//恢复画家保存的状态
painter->restore();
}
2.5、绘制电池电量的文本
void Widget::drawBackText(QPainter *painter)
{
//保存画家的当前状态
painter->save();
//字体设置
QFont font;
font.setFamily("Microsoft Yahei");
font.setPixelSize(14);
painter->setFont(font);
//电量文字
QString value=QString::number(m_currentValue)+QString("%");
//绘制文本
painter->drawText(m_batteryRect,Qt::AlignCenter,value);
//恢复画家保存的状态
painter->restore();
}
3、完整代码
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QPainter>
#include<QtMath>
#include<QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//初始化电池的属性
void init();
//绘制电池边框和头部
void drawBorder(QPainter *painter);
//绘制电池内部背景
void drawBackground(QPainter *painter);
//绘制电池内部电量文字
void drawBackText(QPainter *painter);
protected:
virtual void paintEvent(QPaintEvent *event) override;
private slots:
//改变电池的电量值
void changeValue();
private:
Ui::Widget *ui;
//电池主体部分
QRectF m_batteryRect;
//定时器
QTimer *m_timer;
//内部边距
int m_margin;
//电池电量是否增加或者减少
bool m_isForward;
//电池当前电量
int m_currentValue;
//电池最大电量值
int m_maxValue;
//电池最小电量
int m_minValue;
//电池宽度
int m_batteryWidth;
//电池高度
int m_batteryHeight;
};
#endif // WIDGET_H
widget.cpp:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
,ui(new Ui::Widget)
{
ui->setupUi(this);
init();
m_timer=new QTimer(this);
//设置定时器周期
m_timer->start(300);
connect(m_timer,&QTimer::timeout,this,&Widget::changeValue);
this->setWindowTitle("电池");
}
Widget::~Widget()
{
delete ui;
}
void Widget::init()
{
m_margin=5;
m_isForward=true;
m_currentValue=10;
m_maxValue=100;
m_minValue=0;
m_batteryWidth=150;
m_batteryHeight=60;
}
void Widget::drawBorder(QPainter *painter)
{
//保存画家的当前状态
painter->save();
//设置画笔
painter->setPen(QPen(Qt::gray,8));
//无画刷
painter->setBrush(Qt::NoBrush);
//电池主体居中
m_batteryRect=QRectF((this->width()-m_batteryWidth)/2,(this->height()-m_batteryHeight)/2,
m_batteryWidth,m_batteryHeight);
//绘制电池边框
painter->drawRoundRect(m_batteryRect,15,15);
//绘制电池头部
painter->setPen(QPen(Qt::gray,12));
QLine line(m_batteryRect.topRight().x()+10,m_batteryRect.topRight().y()+10,
m_batteryRect.bottomRight().x()+10,m_batteryRect.bottomRight().y()-10);
painter->drawLine(line);
//恢复画家保存的状态
painter->restore();
}
void Widget::drawBackground(QPainter *painter)
{
//保存画家的当前状态
painter->save();
//确认画刷颜色
if(m_currentValue<=10)
{
//红色
painter->setBrush(QBrush(QColor(204,38,38)));
}
else if(m_currentValue<=20)
{
//橙色
painter->setBrush(QBrush(QColor(190,163,0)));
}
else
{
//绿色
painter->setBrush(QBrush(QColor(50,205,51)));
}
//将电量转化为宽度
double w=m_currentValue*(m_batteryRect.width()-(m_margin*2))/100;
//确认左上角位置
QPointF topLeft=QPointF(m_batteryRect.topLeft().x()+m_margin,m_batteryRect.topLeft().y()+m_margin);
//确认右下角位置
QPointF bottomRight=QPointF(m_batteryRect.topLeft().x()+w+m_margin,m_batteryRect.bottomRight().y()-m_margin);
//绘制电量背景
painter->setPen(Qt::NoPen);
QRectF rectF(topLeft,bottomRight);
painter->drawRoundRect(rectF,10,10);
//恢复画家保存的状态
painter->restore();
}
void Widget::drawBackText(QPainter *painter)
{
//保存画家的当前状态
painter->save();
//字体设置
QFont font;
font.setFamily("Microsoft Yahei");
font.setPixelSize(14);
painter->setFont(font);
//电量文字
QString value=QString::number(m_currentValue)+QString("%");
//绘制文本
painter->drawText(m_batteryRect,Qt::AlignCenter,value);
//恢复画家保存的状态
painter->restore();
}
void Widget::paintEvent(QPaintEvent *event)
{
//创建画家对象
QPainter painter(this);
//设置抗锯齿
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
//绘制电池边框和头部
drawBorder(&painter);
//绘制电池背景
drawBackground(&painter);
//绘制电池内部电量的文字
drawBackText(&painter);
}
void Widget::changeValue()
{
if(m_isForward)
{
m_currentValue+=1;
}
else
{
m_currentValue-=1;
}
if(m_currentValue>=100)
{
m_currentValue=100;
m_isForward=false;
}
if(m_currentValue<=0)
{
m_currentValue=0;
m_isForward=true;
}
update();
}