Qt 仪表盘

在这里插入图片描述

#include "cardisp.h"

#include <QTimer>
#include <QDebug>

// 画圆时的半径
const int CarDisp::radius = 150;
// 最大值
const int CarDisp::maxv = 400;
// 最小值
const int CarDisp::minv = 0;

// 构造函数
CarDisp::CarDisp(QWidget *parent)
    : QWidget(parent)
{
    setWindowTitle("仪表盘");
    // 运行时表针显示的值
    Values = 0;

    QTimer* t = new QTimer();//加入对象树
    t->start(1000);
    //以lambda表达式的形式设置槽函数
    connect(t, &QTimer::timeout, [=]{
        // qDebug() << "hello";
        if(Values > (CarDisp::maxv-5))
        {
            Values = 0;
            setvalues(Values);
        }
        else
        {
            Values += 10;
            setvalues(Values);
        }
    });
}

// 析构函数
CarDisp::~CarDisp()
{
}

// 设置运行时表针显示的值
// 实现更新仪表盘指针
void CarDisp::setvalues(qreal iValues)
{
    // 为仪表盘指针赋值
    Values = iValues;
    // 更新小部件,除非禁用更新或小部件被隐藏。
    // 此函数不会导致立即重绘;相反,当Qt返回到主事件循环时,它调度一个绘画事件进行处理。
    update();
}

// 绘制图像
// 系统内置函数是斜体显示
void CarDisp::paintEvent(QPaintEvent *event)
{
    // 定义一个 QPainter 绘画类的变量
    QPainter painter(this);
    // 指示绘画引擎应该在可能的情况下消除原边缘的混叠
    painter.setRenderHint(QPainter::Antialiasing);
    // 计算出窗体的中心点
    QPoint center(width()/2, height()/2);
    // 保存当前的画工状态(将状态推入堆栈)
    // 保存窗体中心点
    painter.save();


    // 绘制背景圆形
    // 制定绘制图案的起点
    painter.translate(center);
    // 将画家的笔设置为给定的笔
    // 笔定义了如何绘制线条和轮廓,它还定义了文本的颜色
    // Qt::NoPen : 根本没有线。例如,QPainter::drawRect()填充但不绘制任何边界线。
    painter.setPen(Qt::NoPen);
    // 设置画笔颜色
    painter.setBrush(QColor(142,142,142));
    // 背景颜色应该大于仪表盘半径一点一点
    const int bkRadius = radius + 3;
    // 绘制半径为rx和ry的位于中心的椭圆。
    painter.drawEllipse(QPoint(),bkRadius,bkRadius);


    // 绘制刻度线
    // 设置起始的偏移角度
    painter.rotate(-135);
    // 长线的总数量,从 0 开始,一共 11 个
    const int longstep = 10;
    // 短线的总数量,从 0 开始,一共 51 个
    const int shortstep = 50;
    // 使用 for 循环依次画出刻度线
    for(int i = 0; i <= shortstep; i++)
    {
        // 前面80%刻度线为绿色,后面20%刻度线为红色
        painter.setPen((i < shortstep * 0.8) ? QColor(32,243,32) : QColor(243,32,32));

        if(i % (shortstep / longstep) != 0)
        {
            // 绘制短线
            QPoint p1(0,-(radius-8));  // 线的起点
            QPoint p2(0,-radius);  // 线的终点
            painter.drawLine(p1,p2);
        }
        else
        {
            // 绘制长线
            QPoint p1(0,-(radius-14));  // 线的起点
            QPoint p2(0,-radius);  // 线的终点
            painter.drawLine(p1,p2);
        }

        // 设置结束
        painter.rotate(270.0/shortstep);
    }


    // 绘制仪表盘名称和背景矩形
    painter.restore();
    QFontMetrics fm=painter.fontMetrics();
    int tx=center.x();
    int ty=int(center.y()+(radius/1.4142));
    QString title="仪表盘";
    QSize tsz=fm.size(0,title);
    QRect trect(QPoint(tx-tsz.width()/2,ty-tsz.height()/2),tsz);
    painter.setPen(QColor(127,127,127));
    painter.setBrush(QColor(173,163,163));
    painter.drawRoundedRect(trect.adjusted(-6,-4,6,4),3,3);
    painter.setPen(QColor(243,243,243));
    painter.setBrush(Qt::NoBrush);
    painter.drawText(trect,title); // 绘制每个长刻度对应的文字
    painter.setPen(QColor(243,243,243));
    const int hand=radius-21;
    for(int i=0;i<=longstep;i++)
    {
        qreal angle=qDegreesToRadians(-135.0+i*(270.0/longstep));
        QString etext=QString::number(minv+i*(maxv-minv)/longstep);
        QPointF dirvec(qSin(angle),-qCos(angle));
        QPointF ecenter(center.x()+hand*dirvec.x(),center.y()+hand*dirvec.y());
        QSize esz=fm.size(0,etext);
        QRectF erect(QPointF(ecenter.x()-esz.width()/2,ecenter.y()-esz.height()/2),esz);
        painter.drawText(erect,etext);
    }


    // 仪表盘指针绘制
    // 保存当前的画工状态(将状态推入堆栈)
    painter.save();
    QPoint triangle[]={
        {-5,0},
        {0,25-radius},
        {5,0}
    };
    qreal degree=-135.0+270.0*(Values-minv)/(maxv-minv);
    painter.translate(center);
    painter.rotate(degree);
    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::red);
    painter.drawPolygon(triangle,3);
    painter.setPen(QPen(QColor(214,0,0),2));
    painter.drawEllipse(QPoint(),7,7);
    painter.restore();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小π

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值