如下:
绘制步骤
- 先画底部蓝色的圆
- 再画刻度线和刻度值,绘制时,先把painter旋转135度到起始刻度处
- 再画中间的小圆
- 再画指针
- 再画半透明扇形
.h文件
#ifndef GAUGE_H
#define GAUGE_H
#include <QWidget>
#include<QPainter>
//仪表盘
class Gauge : public QWidget
{
Q_OBJECT
Q_PROPERTY(int max READ max WRITE setMax NOTIFY maxChanged FINAL)
Q_PROPERTY(int min READ min WRITE setMin NOTIFY minChanged FINAL)
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged FINAL)
public:
explicit Gauge(QWidget *parent = nullptr);
int max() const;
void setMax(int newMax);
int min() const;
void setMin(int newMin);
int value() const;
void setValue(int newValue);
protected:
void paintEvent(QPaintEvent* ev) override;
private:
int mMax=50;//最大值
int mMin=0;//最小值
int mValue=30;//当前值
signals:
void maxChanged();
void minChanged();
void valueChanged();
};
#endif // GAUGE_H
.cpp文件
#include "gauge.h"
Gauge::Gauge(QWidget *parent)
: QWidget{parent}
{}
void Gauge::paintEvent(QPaintEvent *ev)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
//先将画家移到中心
painter.translate(this->rect().center());
//底部圆盘的半径是:高度或宽度的一半
int r=std::min(width(),height())/2;
//1、先画底部圆盘。采用径向渐变进行填充
painter.save();
QRadialGradient ra(0,0,r);
ra.setColorAt(0,Qt::cyan);
ra.setColorAt(1,Qt::blue);
painter.setBrush(ra);
painter.setPen(Qt::NoPen);//去掉轮廓
painter.drawEllipse(QPoint(0,0),r,r);
painter.restore();
//2、再画刻度线和刻度值
painter.save();
//将画家旋转135°,转到起始刻度线
painter.rotate(135);
painter.setPen(QPen(Qt::white,4));
painter.setFont(QFont("微软雅黑",15));
qreal angle=270*1.0/(mMax-mMin);//刻度线范围所占角度是270度,计算每一个值所占的角度
for(int i=mMin;i<=mMax;++i)
{
//10的整数倍处的刻度线画长一点
if(i%10==0)
{
painter.drawLine(QPoint(r-r/12.0,0),QPoint(r,0));
//获取将要绘制文本的宽高
QFontMetrics fm=painter.fontMetrics();
int width=fm.horizontalAdvance(QString::number(i));
int height=fm.height();
//左半部分的刻度值需要旋转
if(135+i*angle<270)
{
painter.rotate(180);
//文字的起始点x值要更往中心偏一点,且和刻度线间隔10px,y轴往下偏一点
//且x值与下面不同
painter.drawText(QPoint(-r+r/12.0+10,height/3),QString::number(i));
//画完后再转回去
painter.rotate(-180);
}
else
{
//文字的起始点x值要更往中心偏一点,且和刻度线间隔10px,y轴往下偏一点
painter.drawText(QPoint(r-r/12.0-width-10,height/3),QString::number(i));
}
}
else//其余值的刻度线画短一点
{
painter.drawLine(QPoint(r-r/24.0,0),QPoint(r,0));
}
//每画一次,旋转一下
painter.rotate(angle);
}
painter.restore();
//3、再画中间的圆和中间的文字
painter.save();
painter.setPen(QPen(Qt::white,4));
painter.setFont(QFont("微软雅黑",15));
painter.drawEllipse(QPoint(0,0),r/3,r/3);
painter.drawText(QRect(-r/6,-r/6,r/3,r/3),Qt::AlignCenter,QString::number(mValue));
painter.restore();
//4、再画指针
painter.save();
painter.rotate(135);//旋转到起始角度
painter.rotate(mValue*angle);//旋转到当前值对应的角度
painter.setPen(QPen(Qt::white,4));
painter.drawLine(QPoint(r/3,0),QPoint(r-r/12.0-40,0));
painter.restore();
//5、绘制半透明扇形
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(255,0,0,100));
painter.drawPie(QRect(QPoint(-(r-r/12.0-40),-(r-r/12.0-40)),QPoint(r-r/12.0-40,r-r/12.0-40)),
-135*16,
-(mValue*angle)*16);
painter.restore();
}
int Gauge::value() const
{
return mValue;
}
void Gauge::setValue(int newValue)
{
if(newValue>mMax)
{
mValue=mMax;
update();
return;
}
if(newValue<mMin)
{
mValue=mMin;
update();
return;
}
if (mValue == newValue)
return;
mValue = newValue;
emit valueChanged();
update();//值更新后重绘
}
int Gauge::min() const
{
return mMin;
}
void Gauge::setMin(int newMin)
{
if (mMin == newMin)
return;
mMin = newMin;
emit minChanged();
update();
}
int Gauge::max() const
{
return mMax;
}
void Gauge::setMax(int newMax)
{
if (mMax == newMax)
return;
mMax = newMax;
emit maxChanged();
update();
}
知识点:
根据QFontMetrics来获取指定文本的宽度和宽度
//获取将要绘制文本的宽高
QFontMetrics fm=painter.fontMetrics();
int width=fm.horizontalAdvance(QString::number(i));
int height=fm.height();