当前位置: 首页 > article >正文

【Qt绘制仪表盘】

目的

使用Qt的绘制事件绘制一个仪表盘

思路

  1. 需要创建一个带绘制事件的控件
  2. 重写绘制事件
  3. 显示

实现

以下是实现代码,可复制到程序到,直接运行。

.h
// GaugeWidget.h
#ifndef GAUGEWIDGET_H
#define GAUGEWIDGET_H

#include <QWidget>

class GaugeWidget : public QWidget
{
    Q_OBJECT
public:
    explicit GaugeWidget(QWidget *parent = nullptr);

    void setValue(qreal value){m_value = value;}

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    qreal m_value;
};

#endif // GAUGEWIDGET_H

.h分析
  • 继承QWidget类,重新实现void paintEvent(QPaintEvent *event) override;事件;
  • 设置仪表盘当前的数据void setValue(qreal value){m_value = value;}
.cpp
// GaugeWidget.cpp
#include "GaugeWidget.h"
#include <QPainter>

#include <QDebug>
GaugeWidget::GaugeWidget(QWidget *parent) : QWidget(parent), m_value(0)
{

}

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

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    qDebug().noquote() << "[" << __FILE__ << __LINE__ << "]" << this->size();
    // 绘制表盘
    painter.save();
    painter.translate(width()/2, height()/2);
    painter.setPen(Qt::NoPen);
    painter.setBrush(QBrush(QColor(255, 255, 255)));
    painter.drawEllipse(-100, -100, 200, 200);
    painter.setBrush(QBrush(QColor(200, 200, 200)));
    painter.drawEllipse(-95, -95, 190, 190);

    static const int majorTickCount = 12;
    static const int minorTickCount = 5;

    QFont font;
    font.setPointSize(8);
    painter.setFont(font);

    painter.save();
    for (int i = 0; i <= majorTickCount; i++) {
        qreal angle = i * 360.0 / majorTickCount;
        painter.rotate(angle);

        // 绘制刻度线
        if (i < majorTickCount) {
            painter.setPen(QPen(QColor(255, 255, 255), 2));
            painter.drawLine(0, -85, 0, -95);
        }

        // 绘制刻度值
        if (i % 2 == 0) {
            painter.setPen(QPen(QColor(255, 0, 0)));
            qreal value = i * 360.0 / majorTickCount;
            QString text = QString::number(value, 'f', 0);
            QRectF textRect(-50, -100, 100, 100);
            painter.drawText(textRect, Qt::AlignTop|Qt::AlignHCenter, text);
        }

        painter.rotate(-angle);
    }

    for (int i = 0; i < majorTickCount; i++) {
        for (int j = 1; j <= minorTickCount; j++) {
            qreal angle = (i + j / (qreal)minorTickCount) * 360.0 / majorTickCount;
            painter.save();
            painter.rotate(angle);

            painter.setPen(QPen(QColor(255, 255, 255), 1));
            painter.drawLine(0, -90, 0, -95);

            painter.restore();
        }
    }
    painter.restore();

    // 绘制指针
    qreal angle = (m_value / 60.0+0.5) * 360;
    painter.rotate(angle);
    painter.setPen(QPen(QColor(255, 0, 0), 3));
    painter.drawLine(0, 0, 0, 60);
    painter.restore();
}
.cpp分析

paintEvent函数是继承自QWidget的paintEvent事件处理函数,用于绘制小部件的界面。paintEvent函数首先创建一个QPainter对象,然后设置抗锯齿渲染。其余部分主要是绘制仪表盘和指针。具体绘制过程如下:

  1. 绘制表盘:
  • 将绘图原点平移到小部件的中心。

  • 绘制外圆和内圆,用QBrush用来填充圆形。

  • 根据majorTickCount(12)的值循环绘制刻度线和刻度值。每次循环需要计算出角度,然后将绘图原点旋转该角度。

  • 如果当前是大刻度线,则用QPen绘制白色线条。

  • 如果当前是大刻度线的偶数,则用QPen绘制红色刻度值,绘制完成后将绘图原点旋转回来。

  • 根据majorTickCount(12)和minorTickCount(5)的值循环绘制小刻度线。每次循环需要计算出角度,然后将绘图原点旋转该角度,绘制小刻度线,然后将绘图原点旋转回来。

  1. 绘制指针:
  • 根据m_value的值计算出指针应该指向的角度,并将绘图原点旋转该角度。
  • 用QPen绘制红色的指针线。
  • 将绘图原点旋转回来。
在MainWindow中使用自定义控件类GaugeWidget,测试表盘绘制效果:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "GaugeWidget.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    GaugeWidget *gaugeWidget = new GaugeWidget;
    setCentralWidget(gaugeWidget);
    gaugeWidget->setValue(40);
}

MainWindow::~MainWindow()
{
    delete ui;
}

编译运行程序,效果如下:

在这里插入图片描述

结论

繁华到极致,腐朽到荒凉


http://www.kler.cn/a/148491.html

相关文章:

  • 相机光学(四十二)——sony的HDR技术
  • AutoCad 无界面开发
  • AWS认证SAA-C0303每日一题
  • 【初阶数据结构与算法】链表刷题之移除链表元素、反转链表、找中间节点、合并有序链表、链表的回文结构
  • 【Java SE】接口类型
  • 【STM32】基于SPI协议读写SD,详解!
  • CentOS7.9虚拟机EDA环境,支持模拟集成电路、数字集成电路、数模混合设计全流程,包含工艺库
  • LeetCode(33)最小覆盖子串【滑动窗口】【困难】
  • java BASE64Encoder BASE64Decoder 废弃
  • 大数据机房迁移该按照什么步骤进行 |数据中心
  • 【Java学习笔记】73 - 正则表达式
  • 算法通关村-----数据流的中位数
  • 企业源代码防泄密的有什么痛点及难点?
  • 安装MySQL搭建论坛
  • 通过测试驱动开发(TDD)的方式开发Web项目
  • Rust UI开发(一):使用iced构建UI时,如何在界面显示中文字符
  • 项目问题总结
  • 华为OD机试真题-整数对最小和-2023年OD统一考试(C卷)
  • 简要介绍Spring原生框架与Spring是轻量级框架的原因
  • 原生DOM事件、react16、17和Vue合成事件
  • Git控制指令
  • C语言枚举的作用是什么?
  • Java中类的类型判断技巧以及没有无参构造函数时的应对策略。isInstance()方法解析
  • PTA:编程实现strncpy函数功能(C语言)
  • Docker笔记-Docker搭建最新版zabbix服务端(2023-07-31)
  • Android开源框架--Dagger2详解