仪表盘

如下:

绘制步骤

  1. 先画底部蓝色的圆
  2. 再画刻度线和刻度值,绘制时,先把painter旋转135度到起始刻度处
  3. 再画中间的小圆
  4. 再画指针
  5. 再画半透明扇形

.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();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值