开源 C++ QT Widget 开发(九)图表--仪表盘

文章的目的为了记录使用C++ 进行QT Widget 开发学习的经历。临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 C++ QT Widget 开发(一)工程文件结构-CSDN博客

开源 C++ QT Widget 开发(二)基本控件应用-CSDN博客

开源 C++ QT Widget 开发(三)图表--波形显示器-CSDN博客

开源 C++ QT Widget 开发(四)文件--二进制文件查看编辑-CSDN博客

开源 C++ QT Widget 开发(五)通讯--串口调试-CSDN博客

开源 C++ QT Widget 开发(六)通讯--TCP调试-CSDN博客

开源 C++ QT Widget 开发(七)线程--多线程及通讯-CSDN博客

开源 C++ QT Widget 开发(八)网络--Http文件下载-CSDN博客

开源 C++ QT Widget 开发(九)图表--仪表盘-CSDN博客

推荐链接:

开源 java android app 开发(一)开发环境的搭建-CSDN博客

开源 java android app 开发(二)工程文件结构-CSDN博客

开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客

开源 java android app 开发(四)GUI界面重要组件-CSDN博客

开源 java android app 开发(五)文件和数据库存储-CSDN博客

开源 java android app 开发(六)多媒体使用-CSDN博客

开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客

开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客

开源 java android app 开发(九)后台之线程和服务-CSDN博客

开源 java android app 开发(十)广播机制-CSDN博客

开源 java android app 开发(十一)调试、发布-CSDN博客

开源 java android app 开发(十二)封库.aar-CSDN博客

推荐链接:

开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

本章主要内容:基于 Qt框架实现的仪表盘控件。

目录:

1.源码分析

2.所有源码

3.效果演示

一、核心源码分析

  1. 外观特点

颜色方案:采用黑色背景与亮蓝色(青绿色)的刻度、文字和指针

警告区域:使用橙红色半透明区域标识超速警告

数字显示:底部有数字显示当前值和单位

  1. 公共接口

这些方法提供了对仪表盘外观和数据的控制。

复制代码
void setValue(double value);          // 设置当前速度值
void setRange(double min, double max); // 设置量程范围
void setUnits(const QString &units);  // 设置单位
void setWarningValue(double value);   // 设置警告值
  1. 几何参数

仪表盘覆盖270度的圆弧范围。

复制代码
double m_startAngle{135};  // 起始角度(135度 - 左下)
double m_endAngle{360+45}; // 结束角度(405度 - 右下)
  1. 实现文件 (dashboard.cpp)

绘制组件:

drawBackground(): 绘制背景和渐变效果

drawWarningZone(): 绘制警告区域

drawTicks(): 绘制刻度和数字

drawNeedle(): 绘制指针

drawDigitalDisplay(): 绘制数字显示

坐标计算:

getTickPosition(): 计算刻度位置

getNeedleEndPoint(): 计算指针端点位置

二、所有源码

1.Dashboard.h文件

复制代码
#ifndef DASHBOARD_H
#define DASHBOARD_H

#include <QWidget>
#include <QTimer>

class Dashboard : public QWidget
{
    Q_OBJECT

public:
    explicit Dashboard(QWidget *parent = nullptr);

    // 公共接口函数
    void setValue(double value);          // 设置当前速度值
    void setRange(double min, double max); // 设置量程范围
    void setUnits(const QString &units);  // 设置单位
    void setWarningValue(double value);   // 设置警告值

    double value() const { return m_value; }
    double minValue() const { return m_minValue; }
    double maxValue() const { return m_maxValue; }

protected:
    void paintEvent(QPaintEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;

private:
    void drawBackground(QPainter &painter);
    void drawTicks(QPainter &painter);
    void drawNumbers(QPainter &painter);
    void drawNeedle(QPainter &painter);
    void drawDigitalDisplay(QPainter &painter);
    void drawWarningZone(QPainter &painter);

    // 坐标转换函数
    QPointF getTickPosition(double value, double length) const;
    QPointF getNeedleEndPoint() const;

    // 仪表盘参数
    double m_value{0};
    double m_minValue{0};
    double m_maxValue{260};
    double m_warningValue{200};
    QString m_units{"km/h"};

    // 外观参数
    // 外观参数 - 亮浅蓝色主题
    QColor m_backgroundColor{QColor(0, 0, 0)};  // 亮浅蓝色
    QColor m_scaleColor{QColor(9, 245, 249)};           // 深蓝色刻度
    //QColor m_needleColor{Qt::red};                    // 红色指针
    //QColor m_textColor{Qt::white};                    // 黑色文字
    QColor m_needleColor{QColor(9, 245, 249)};                    // 红色指针
    QColor m_textColor{QColor(9, 245, 249)};                    // 黑色文字
    QColor m_warningColor{QColor(255, 69, 0)};        // 橙红色警告
    //QColor m_digitalBgColor{QColor(240, 240, 240, 220)}; // 浅灰色数字背景
    QColor m_digitalBgColor{QColor(0, 0, 0)}; // 浅灰色数字背景

    // 几何参数
    QRectF m_dialRect;
    QPointF m_center;
    double m_radius{0};
    double m_startAngle{135};  // 起始角度(度)
    double m_endAngle{360+45};    // 结束角度(度)
};

#endif // DASHBOARD_H
  1. Dashboard.cpp文件

    #include "dashboard.h"
    #include <QPainter>
    #include <QConicalGradient>
    #include <QtMath>
    #include <QFontDatabase>
    #include <QDebug>
    Dashboard::Dashboard(QWidget *parent) : QWidget(parent)
    {
    // 设置默认大小
    setMinimumSize(300, 300);

    复制代码
     // 可选:添加字体(确保数字显示美观)
     int fontId = QFontDatabase::addApplicationFont(":/fonts/digital.ttf");
     if (fontId == -1) {
         // 使用系统字体作为备选
         qDebug() << "Failed to load digital font, using system font";
     }

    }

    void Dashboard::setValue(double value)
    {
    // 限制值在范围内
    m_value = qBound(m_minValue, value, m_maxValue);
    update(); // 触发重绘
    }

    void Dashboard::setRange(double min, double max)
    {
    m_minValue = min;
    m_maxValue = max;
    if (m_value > m_maxValue) m_value = m_maxValue;
    if (m_value < m_minValue) m_value = m_minValue;
    update();
    }

    void Dashboard::setUnits(const QString &units)
    {
    m_units = units;
    update();
    }

    void Dashboard::setWarningValue(double value)
    {
    m_warningValue = value;
    update();
    }

    void Dashboard::paintEvent(QPaintEvent *event)
    {
    Q_UNUSED(event);

    复制代码
     QPainter painter(this);
     painter.setRenderHint(QPainter::Antialiasing);
    
     // 计算几何参数
     m_center = rect().center();
     m_radius = qMin(width(), height()) * 0.4;
     m_dialRect = QRectF(m_center.x() - m_radius, m_center.y() - m_radius,
                        m_radius * 2, m_radius * 2);
    
     // 绘制各个部件
     drawBackground(painter);
     drawWarningZone(painter);
     drawTicks(painter);
     drawNumbers(painter);
     drawNeedle(painter);
     drawDigitalDisplay(painter);

    }

    void Dashboard::resizeEvent(QResizeEvent *event)
    {
    QWidget::resizeEvent(event);
    update(); // 尺寸变化时重绘
    }

    void Dashboard::drawBackground(QPainter &painter)
    {
    // 绘制外圆
    painter.setPen(QPen(m_scaleColor, 2));
    painter.setBrush(m_backgroundColor);
    painter.drawEllipse(m_dialRect);

    复制代码
     // 绘制内圆(创建立体感)
     QRadialGradient gradient(m_center, m_radius);
     gradient.setColorAt(0, QColor(100, 100, 100));
     gradient.setColorAt(1, m_backgroundColor);
     painter.setBrush(gradient);
     painter.drawEllipse(m_center, m_radius * 0.9, m_radius * 0.9);

    }

    void Dashboard::drawWarningZone(QPainter &painter)
    {
    if (m_warningValue <= m_minValue) return;

    复制代码
     double warningStartAngle = m_startAngle + (m_warningValue - m_minValue) /
                               (m_maxValue - m_minValue) * (m_endAngle - m_startAngle);
    
     QPainterPath path;
     path.arcMoveTo(m_dialRect, warningStartAngle);
     path.arcTo(m_dialRect, warningStartAngle, m_endAngle - warningStartAngle);
    
     QPen pen(Qt::NoPen);
     painter.setPen(pen);
     painter.setBrush(QColor(255, 0, 0, 80)); // 半透明红色
     painter.drawPath(path);

    }

    void Dashboard::drawTicks(QPainter &painter)
    {
    painter.setPen(QPen(m_scaleColor, 2));

    复制代码
     // 主刻度(每20单位)
     for (int i = m_minValue; i <= m_maxValue; i += 20) {
         if (i > m_maxValue) break;
    
         QPointF start = getTickPosition(i, m_radius * 0.85);
         QPointF end = getTickPosition(i, m_radius * 0.95);
         painter.drawLine(start, end);
     }
    
     // 次刻度(每10单位)
     painter.setPen(QPen(m_scaleColor, 1));
     for (int i = m_minValue; i <= m_maxValue; i += 10) {
         if (i % 20 == 0) continue; // 跳过主刻度
    
         QPointF start = getTickPosition(i, m_radius * 0.9);
         QPointF end = getTickPosition(i, m_radius * 0.95);
         painter.drawLine(start, end);
     }

    }

    void Dashboard::drawNumbers(QPainter &painter)
    {
    painter.setPen(m_textColor);
    QFont font = painter.font();
    font.setPointSize(10);
    font.setBold(true);
    painter.setFont(font);

    复制代码
     for (int i = m_minValue; i <= m_maxValue; i += 20) {
         if (i > m_maxValue) break;
    
         QPointF pos = getTickPosition(i, m_radius * 0.75);
         QRectF textRect(pos.x() - 20, pos.y() - 10, 40, 20);
         painter.drawText(textRect, Qt::AlignCenter, QString::number(i));
     }

    }

    void Dashboard::drawNeedle(QPainter &painter)
    {
    QPointF needleEnd = getNeedleEndPoint();

    复制代码
     // 绘制指针
     QPen needlePen(m_needleColor, 3);
     needlePen.setCapStyle(Qt::RoundCap);
     painter.setPen(needlePen);
     painter.drawLine(m_center, needleEnd);
    
     // 绘制中心圆
     painter.setPen(Qt::NoPen);
     painter.setBrush(m_needleColor);
     painter.drawEllipse(m_center, 5, 5);

    }

    void Dashboard::drawDigitalDisplay(QPainter &painter)
    {
    // 绘制数字显示区域
    QRectF digitalRect(m_center.x() - 60, m_center.y() + m_radius * 0.3, 120, 40);
    painter.setPen(Qt::NoPen);
    painter.setBrush(m_digitalBgColor);
    painter.drawRoundedRect(digitalRect, 5, 5);

    复制代码
     // 绘制数字
     painter.setPen(m_textColor);
     QFont font = painter.font();
     font.setPointSize(16);
     font.setBold(true);
     painter.setFont(font);
    
     QString displayText = QString("%1 %2").arg(m_value, 0, 'f', 0).arg(m_units);
     painter.drawText(digitalRect, Qt::AlignCenter, displayText);

    }

    QPointF Dashboard::getTickPosition(double value, double length) const
    {
    double angle = m_startAngle + (value - m_minValue) /
    (m_maxValue - m_minValue) * (m_endAngle - m_startAngle);
    double radian = qDegreesToRadians(angle);

    复制代码
     return QPointF(m_center.x() + length * qCos(radian),
                   m_center.y() + length * qSin(radian));

    }

    QPointF Dashboard::getNeedleEndPoint() const
    {
    double angle = m_startAngle + (m_value - m_minValue) /
    (m_maxValue - m_minValue) * (m_endAngle - m_startAngle);
    double radian = qDegreesToRadians(angle);

    复制代码
     return QPointF(m_center.x() + m_radius * 0.7 * qCos(radian),
                   m_center.y() + m_radius * 0.7 * qSin(radian));

    }

3.mainwindow.cpp文件

复制代码
#include "mainwindow.h"
#include "Dashboard.h"
#include <QVBoxLayout>
#include <QSlider>
#include <QLabel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // 创建中央部件
    QWidget *centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);

    // 创建布局
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);

    // 创建仪表盘
    Dashboard *dashboard = new Dashboard(this);
    dashboard->setRange(0, 240);
    dashboard->setWarningValue(200);
    dashboard->setValue(60); // 初始值

    // 创建控制滑块
    QSlider *slider = new QSlider(Qt::Horizontal);
    slider->setRange(0, 260);
    slider->setValue(60);

    // 连接信号槽
    connect(slider, &QSlider::valueChanged, dashboard, &Dashboard::setValue);

    // 添加到布局
    layout->addWidget(dashboard);
    layout->addWidget(slider);

    resize(400, 500);
}

MainWindow::~MainWindow()
{
}

三、效果演示

相关推荐
火山kim4 小时前
一文速通liunx命令
java·linux·运维·服务器
long_run4 小时前
C++之常用容器
c++
水饺编程4 小时前
Windows 命令行:cd 命令1,cd 命令的简单使用
c语言·c++·windows·visual studio
一枝小雨4 小时前
【C++】深入解析C++嵌套依赖类型与typename关键字
开发语言·c++·笔记·学习笔记
水饺编程5 小时前
Windows 命令行:父目录与子目录
c语言·c++·windows·visual studio
NocoBase5 小时前
7 款替代 Zapier 的开源工作流工具推荐
低代码·开源·工作流引擎
Orchestrator_me5 小时前
centos目录大小查看与清理
linux·运维·centos
算家计算5 小时前
70亿参数媲美闭源巨头!Seed-X-PPO-7B本地部署教程:触手可及的顶级翻译模型
人工智能·开源
huangyuchi.5 小时前
【Linux系统】万字解析,进程间的信号
linux·服务器·信号处理·信号产生·linux信号·信号保存·操作系统如何运行