《Qt/UI美化实战课程》| 第五章 自定义仪表盘(美观/高度定制/自适应大小)| 2. 使用仪表盘(1) 新建项目、界面布局

 《Qt/UI美化实战课程》新课首发

(1)无边框窗口(11讲)

(2)图标字体(10讲)

(3)官方图表QChart:曲线、柱状图、饼图(20+讲)

(4)第三方图表QCustomPlot:曲线、柱状图、饼图(20+讲)

(5)监控日志高亮(共 14 讲)

(6)仪表盘(16讲)

(7)天气预报(11+讲)

(8)基础控件(15+讲)

(9)高级控件(12+讲)

(10)精美换肤(15+讲)

详情参见个人主页的置顶视频(明王出品,必属精品)

需要系统跟明王学习的小伙伴,可以直接加明王:coding4096

(1)总课时:超 120+ 讲,每日更新

(2)讲课风格:从零新建项目,从零一行行写代码

(3)提供资料:视频教程+配套源码+详细笔记

本章将会从零实现一个自定义控件-仪表盘,它支持:

✅ 自定义起始角度、圆弧跨度

✅ 自定义圆环宽度、颜色、样式

✅ 支持背景圆环、当前值圆环

✅ 自定义刻度线的颜色、位置、大小刻度的数目

✅ 自定义刻度值的颜色、位置、最大最小值、精度(小数位数)

✅ 自定义显示标题:温度、湿度、电流、电压等(标题完美地显示在缺口处)

✅ 支持动画特性:从一个值变为另一个值,指针会平滑旋转

✅ 支持仪表盘自适应大小(仪表盘缩放时,圆环宽度、刻度线、刻度值、标题大小等,自适应地缩放)

本章会从零开始,自定义实现一个仪表盘控件。会实现的2个效果:

本节先创建项目,并完成整体界面布局。

1. 新建项目

创建一个名为 GaugeDemo 的项目,直接继承 QWidget,取消勾选 "Generate form",手写布局,如下:

创建完成,项目目录如下:

2. 完成布局

界面整体效果,如下:

整体采用水平布局,左侧和右侧均采用垂直布局

首先,把仪表盘的源码文件 gauge.cppgauge.h 拷贝到项目的根目录下,如下:

右键左侧的项目文件名,选择 "添加现有文件...",把这两个文件,添加到项目当中,如下:

然后,来到 widget.h 中,声明布局相关的成员变量和成员函数,如下:

#include <QLineEdit>
#include <QLabel>
#include <QSlider>
#include <QSpinBox>
#include <QComboBox>
#include <QCheckBox>
#include "gauge.h"

class Widget : public QWidget
{
private:
    void initLeft();
    void initRight();
    
private:
    QWidget* leftWidget;
    QWidget* rightWidget;

    // 左侧
    Gauge* gauge;
    QSlider* slider;

    // 右侧
    // 基础设置
    QLineEdit* leMinValue;
    QLineEdit* leMaxValue;
    QLineEdit* lePrecision;
    QLineEdit* leUnit;
    QLineEdit* leTitle;
    QLabel* lblTitleColor;

    // 圆环
    QLineEdit* leStartAngle;
    QLineEdit* leSpanAngle;
    QSpinBox* sbRingWidth;
    QLabel* lblRingColor;
    QLabel* lblCurrentRingColor;
    QComboBox* cboRingStyle;

    // 刻度
    QLineEdit* leMajorScale;
    QLineEdit* leMinorScale;
    QLabel* lblScaleColor;
    QLabel* lblScaleValuesColor;
    QComboBox* cboScalePos;

    // 指针
    QLabel* lblPointerColor;
    QComboBox* cboPointerStyle;
    QCheckBox* chkAnimation;
    QLineEdit* leAnimationStep;
};
然后,来到 widget.cpp 构造中,实现布局,如下:
#include <QHBoxLayout>
#include <QVBoxLayout>

Widget::Widget(QWidget* parent) : QWidget(parent)
{
    this->setWindowTitle("《Qt/UI美化实战课程》-第五章 自定义仪表盘(总课时超120+讲 VX: coding4096)");
    this->setStyleSheet("Font: 18px;");

    // 1. 布局
    QHBoxLayout* mainLayout = new QHBoxLayout(this);

    leftWidget = new QWidget(this);
    QVBoxLayout* leftLayout = new QVBoxLayout(leftWidget);
    leftWidget->setObjectName("leftWidget");
    leftWidget->setStyleSheet("QWidget#leftWidget{background-color: rgb( 58, 67, 90);}");

    rightWidget = new QWidget(this);
    QVBoxLayout* rightLayout = new QVBoxLayout(rightWidget);
    rightWidget->setObjectName("rightWidget");
    rightWidget->setStyleSheet("QWidget#rightWidget{background-color: rgb( 150, 180,220);}");

    initLeft();
    initRight();

    mainLayout->addWidget(leftWidget);
    mainLayout->addWidget(rightWidget);
    mainLayout->setStretchFactor(leftWidget, 3);
    mainLayout->setStretchFactor(rightWidget, 1);
}
此时,运行效果如下:

接下来分别填充左侧布局和右侧布局

2.1 左侧布局

左侧整体采用垂直布局,上面一个仪表盘,下边一个滑块用于改变仪表盘的数值

来到 widget.cpp,实现 initLeft() 函数,如下:

void Widget::initLeft()
{
    gauge = new Gauge(this);
    gauge->setMinimumWidth(300);

    slider = new QSlider(this);
    slider->setOrientation(Qt::Horizontal);
    slider->setRange(0, 100);

    leftWidget->layout()->addWidget(gauge);
    leftWidget->layout()->addWidget(slider);
}
此时,运行效果:

2.1 右侧布局

右侧整体采用垂直布局,垂直分布着 4GroupBox,分别用来基础设置、圆环设置、刻度设置、指针设置

来到 widget.cpp,实现 initRight() 函数,如下:

#include <QGroupBox>

void Widget::initRight()
{
    QVBoxLayout* rightLayout = static_cast<QVBoxLayout*>(rightWidget->layout());

    // 1. 基础设置
    QGroupBox* basicGroup = new QGroupBox("基础设置", this);

    QGridLayout* basicLayout = new QGridLayout(basicGroup);

    QLabel* lbl1 = new QLabel("范围");
    QLabel* lbl2 = new QLabel("小数精度");
    QLabel* lbl3 = new QLabel("单位");
    QLabel* lbl4 = new QLabel("标题");
    QLabel* lbl5 = new QLabel("颜色");

    lbl1->setAlignment(Qt::AlignRight);
    lbl2->setAlignment(Qt::AlignRight);
    lbl3->setAlignment(Qt::AlignRight);
    lbl4->setAlignment(Qt::AlignRight);
    lbl5->setAlignment(Qt::AlignRight);

    lbl1->setMinimumWidth(100);

    basicLayout->addWidget(lbl1, 0, 0);
    basicLayout->addWidget(lbl2, 1, 0);
    basicLayout->addWidget(lbl3, 2, 0);
    basicLayout->addWidget(lbl4, 3, 0);
    basicLayout->addWidget(lbl5, 4, 0);

    QHBoxLayout* rangeLayout = new QHBoxLayout();
    leMinValue = new QLineEdit(this);
    QLabel* lbl = new QLabel("-", this);
    leMaxValue = new QLineEdit(this);
    rangeLayout->addWidget(leMinValue);
    rangeLayout->addWidget(lbl);
    rangeLayout->addWidget(leMaxValue);

    lePrecision = new QLineEdit(this);
    leUnit = new QLineEdit(this);
    leTitle = new QLineEdit(this);
    lblTitleColor = new QLabel(this);

    basicLayout->addLayout(rangeLayout, 0, 1);
    basicLayout->addWidget(lePrecision, 1, 1);
    basicLayout->addWidget(leUnit, 2, 1);
    basicLayout->addWidget(leTitle, 3, 1);
    basicLayout->addWidget(lblTitleColor, 4, 1);

    rightLayout->addWidget(basicGroup);

    // 2. 圆环设置
    QGroupBox* ringGroup = new QGroupBox("圆环", this);

    QGridLayout* ringLayout = new QGridLayout(ringGroup);

    QLabel* lbl6 = new QLabel("起始角度");
    QLabel* lbl7 = new QLabel("跨越角度");
    QLabel* lbl8 = new QLabel("宽度");
    QLabel* lbl9 = new QLabel("背景颜色");
    QLabel* lbl10 = new QLabel("当前颜色");
    QLabel* lbl11 = new QLabel("样式");

    lbl6->setAlignment(Qt::AlignRight);
    lbl7->setAlignment(Qt::AlignRight);
    lbl8->setAlignment(Qt::AlignRight);
    lbl9->setAlignment(Qt::AlignRight);
    lbl10->setAlignment(Qt::AlignRight);
    lbl11->setAlignment(Qt::AlignRight);

    lbl6->setMinimumWidth(100);

    ringLayout->addWidget(lbl6, 0, 0);
    ringLayout->addWidget(lbl7, 1, 0);
    ringLayout->addWidget(lbl8, 2, 0);
    ringLayout->addWidget(lbl9, 3, 0);
    ringLayout->addWidget(lbl10, 4, 0);
    ringLayout->addWidget(lbl11, 5, 0);

    leStartAngle = new QLineEdit(this);
    leSpanAngle = new QLineEdit(this);
    sbRingWidth = new QSpinBox(this);
    lblRingColor = new QLabel(this);
    lblCurrentRingColor = new QLabel(this);
    cboRingStyle = new QComboBox(this);

    ringLayout->addWidget(leStartAngle, 0, 1);
    ringLayout->addWidget(leSpanAngle, 1, 1);
    ringLayout->addWidget(sbRingWidth, 2, 1);
    ringLayout->addWidget(lblRingColor, 3, 1);
    ringLayout->addWidget(lblCurrentRingColor, 4, 1);
    ringLayout->addWidget(cboRingStyle, 5, 1);

    rightLayout->addWidget(ringGroup);

    // 3. 刻度设置
    QGroupBox* scaleGroup = new QGroupBox("刻度", this);

    QGridLayout* scaleLayout = new QGridLayout(scaleGroup);

    QLabel* lbl12 = new QLabel("大刻度");
    QLabel* lbl13 = new QLabel("小刻度");
    QLabel* lbl14 = new QLabel("刻度线颜色");
    QLabel* lbl15 = new QLabel("刻度值颜色");
    QLabel* lbl16 = new QLabel("位置");

    lbl12->setAlignment(Qt::AlignRight);
    lbl13->setAlignment(Qt::AlignRight);
    lbl14->setAlignment(Qt::AlignRight);
    lbl15->setAlignment(Qt::AlignRight);
    lbl16->setAlignment(Qt::AlignRight);

    lbl12->setMinimumWidth(100);

    scaleLayout->addWidget(lbl12, 0, 0);
    scaleLayout->addWidget(lbl13, 1, 0);
    scaleLayout->addWidget(lbl14, 2, 0);
    scaleLayout->addWidget(lbl15, 3, 0);
    scaleLayout->addWidget(lbl16, 4, 0);

    leMajorScale = new QLineEdit(this);
    leMinorScale = new QLineEdit(this);
    lblScaleColor = new QLabel(this);
    lblScaleValuesColor = new QLabel(this);
    cboScalePos = new QComboBox(this);

    scaleLayout->addWidget(leMajorScale, 0, 1);
    scaleLayout->addWidget(leMinorScale, 1, 1);
    scaleLayout->addWidget(lblScaleColor, 2, 1);
    scaleLayout->addWidget(lblScaleValuesColor, 3, 1);
    scaleLayout->addWidget(cboScalePos, 4, 1);

    rightLayout->addWidget(scaleGroup);

    // 4. 指针设置
    QGroupBox* pointerGroup = new QGroupBox("指针", this);

    QGridLayout* pointerLayout = new QGridLayout(pointerGroup);

    QLabel* lbl17 = new QLabel("颜色");
    QLabel* lbl18 = new QLabel("样式");
    QLabel* lbl19 = new QLabel("动画");
    QLabel* lbl20 = new QLabel("动画步长");

    lbl17->setAlignment(Qt::AlignRight);
    lbl18->setAlignment(Qt::AlignRight);
    lbl19->setAlignment(Qt::AlignRight);
    lbl20->setAlignment(Qt::AlignRight);

    lbl17->setMinimumWidth(100);

    pointerLayout->addWidget(lbl17, 0, 0);
    pointerLayout->addWidget(lbl18, 1, 0);
    pointerLayout->addWidget(lbl19, 2, 0);
    pointerLayout->addWidget(lbl20, 3, 0);

    lblPointerColor = new QLabel(this);
    cboPointerStyle = new QComboBox(this);
    chkAnimation = new QCheckBox(this);
    leAnimationStep = new QLineEdit(this);

    pointerLayout->addWidget(lblPointerColor, 0, 1);
    pointerLayout->addWidget(cboPointerStyle, 1, 1);
    pointerLayout->addWidget(chkAnimation, 2, 1);
    pointerLayout->addWidget(leAnimationStep, 3, 1);

    rightLayout->addWidget(pointerGroup);

    // 5. 弹簧
    QSpacerItem* item = new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding);
    rightLayout->addItem(item);
}
此时,运行效果:


                
  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
很高兴为您提供帮助!以下是一个简单的基于QT仪表盘控件类实现: class Dashboard : public QWidget { Q_OBJECT public: Dashboard(QWidget *parent = nullptr); void setRange(qreal min, qreal max); void setValue(qreal value); protected: void paintEvent(QPaintEvent *); private: qreal m_min; qreal m_max; qreal m_value; }; void Dashboard::setRange(qreal min, qreal max) { m_min = min; m_max = max; } void Dashboard::setValue(qreal value) { m_value = value; } void Dashboard::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); // 绘制背景 painter.fillRect(rect(), Qt::white); // 计算当前值在范围内的比例 qreal ratio = (m_value - m_min) / (m_max - m_min); // 绘制进度条 painter.setBrush(Qt::green); painter.setPen(Qt::NoPen); painter.drawPie(rect(), 225*16, (ratio*270)*16); // 绘制刻度线 painter.setBrush(Qt::black); painter.setPen(Qt::NoPen); qreal tickCount = (m_max - m_min) / 10.0; qreal angleStep = 270 / tickCount; for (int i = 0; i <= tickCount; ++i) { qreal angle = i * angleStep; qreal x1 = 0.4 * rect().width() / 2 * qCos(qDegreesToRadians(angle + 45)); qreal y1 = 0.4 * rect().width() / 2 * qSin(qDegreesToRadians(angle + 45)); qreal x2 = 0.45 * rect().width() / 2 * qCos(qDegreesToRadians(angle + 45)); qreal y2 = 0.45 * rect().width() / 2 * qSin(qDegreesToRadians(angle + 45)); painter.drawLine(width() / 2 + x1, height() / 2 + y1, width() / 2 + x2, height() / 2 + y2); } // 绘制文字 painter.setBrush(Qt::black); painter.setPen(Qt::NoPen); QFont font("Helvetica", 12, QFont::Bold); painter.setFont(font); painter.drawText(rect(), Qt::AlignCenter, QString::number(m_value)); } // 使用方法示例: // Dashboard *dashboard = new Dashboard(); // dashboard->setRange(0, 100); // dashboard->setValue(50); // dashboard->show(); 希望对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大轮明王讲QT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值