1、功能
制作一个汽车速度表
2、实现
从外到内进行绘制,初始化画布,画渐变色外圈,画刻度,写刻度文字,画指针,画扇形,画内圈渐变色,画黑色内圈,写当前值
3、效果
4、源码
a、头文件
#ifndef CARDASHBOARD_H
#define CARDASHBOARD_H#include <QTimer>
#include <QWidget>class CarDashboard : public QWidget {Q_OBJECTpublic:CarDashboard(QWidget *parent = nullptr);~CarDashboard();protected:void paintEvent(QPaintEvent *event);private:void startSpeed();void initCanvas(QPainter &painter);void drawOutterShine(QPainter &painter);void drawScale(QPainter &painter);void drawScaleText(QPainter &painter);void drawPointer(QPainter &painter);void drawSector(QPainter &painter);void drawInnerShine(QPainter &painter);void drawInnerBlack(QPainter &painter);void drawCurrentValue(QPainter &painter);private:const int kScaleAngle = 240; // 刻度扇形角度const int kScaleNum = 60; // 刻度数量const int kLengthScale = 5; // 长刻度与刻度比例const int kOneScaleValue = 4; // 一个刻度对应值double av_angle_ = 0; // 平均角度int start_rotate_angle_clock_ = 0; // 起始旋转角度(顺时针)(推算出来的)int start_rotate_angle_ = 0; // 起始旋转角度(逆时针)(推算出来的)int pointer_dir_ = 0; // 指针旋转方向int scale_value_ = 0; // 刻度值int height_half_ = 0; // 高度一半int min_unit_ = 0; // 最小单位值int font_size_ = 0; // 字体大小int scale_text_radius_ = 0; // 刻度文字半径int indent_value_ = 0; // 刻度缩进值QTimer *timer_ = nullptr; // 定时器
};
#endif // CARDASHBOARD_H
b、源文件
#include "cardashboard.h"#include <QPainter>
#include <QtMath>CarDashboard::CarDashboard(QWidget *parent) : QWidget(parent) {av_angle_ = kScaleAngle * 1.0 / kScaleNum;start_rotate_angle_clock_ = -kScaleAngle / 2 + 270;start_rotate_angle_ = kScaleAngle / 2 + 90;startSpeed();
}CarDashboard::~CarDashboard() {}void CarDashboard::startSpeed() {timer_ = new QTimer(this);connect(timer_, &QTimer::timeout, [=]() {update();if (pointer_dir_ == 0) {scale_value_++;if (scale_value_ >= kScaleNum) {pointer_dir_ = 1;}} else if (pointer_dir_ == 1) {scale_value_--;if (scale_value_ == 0) {pointer_dir_ = 0;}}});timer_->setInterval(50);timer_->start();
}void CarDashboard::initCanvas(QPainter &painter) {painter.setRenderHint(QPainter::Antialiasing, true);// 黑色背景painter.setBrush(Qt::black);painter.drawRect(rect());painter.setBrush(Qt::NoBrush);painter.translate(QPoint(width() / 2, height() * 0.6));height_half_ = height() / 2; // 高度一半min_unit_ = height() / 16; // 最小单位值font_size_ = min_unit_ * 2 / 5; // 字体大小scale_text_radius_ = height_half_ - min_unit_ * 7 / 8; // 刻度文字半径indent_value_ = min_unit_ / 8; // 刻度缩进大
}void CarDashboard::drawOutterShine(QPainter &painter) {const int radius = height_half_ + min_unit_ / 2;painter.save();QRect rect(-radius, -radius, radius * 2, radius * 2);QRadialGradient gradient(0, 0, radius);gradient.setColorAt(1.0, QColor(255, 0, 0, 200));gradient.setColorAt(0.97, QColor(255, 0, 0, 120));gradient.setColorAt(0.92, QColor(0, 0, 0, 0));gradient.setColorAt(0.0, QColor(0, 0, 0, 0));painter.setPen(Qt::NoPen);painter.setBrush(gradient);painter.drawPie(rect, start_rotate_angle_ * 16, -av_angle_ * kScaleNum * 16);painter.restore();
}void CarDashboard::drawScale(QPainter &painter) {painter.save();painter.setPen(QPen(Qt::white, 3));painter.rotate(start_rotate_angle_clock_);for (int i = 0; i <= kScaleNum; i++) {if (i >= 40) {painter.setPen(QPen(Qt::red, 3));}if (i % kLengthScale == 0) { // 长刻度painter.drawLine(height_half_ - min_unit_ / 2, 0,height_half_ - indent_value_, 0);} else { // 短刻度painter.drawLine(height_half_ - min_unit_ / 4, 0,height_half_ - indent_value_, 0);}painter.rotate(av_angle_);}painter.restore();
}// 这个函数是难点
void CarDashboard::drawScaleText(QPainter &painter) {painter.save();painter.setPen(QPen(Qt::white, 3));QFont font("Arial", font_size_);font.setBold(true);painter.setFont(font);for (int i = 0; i <= kScaleNum; i++) {if (i % kLengthScale == 0) {// 保存坐标painter.save();// 正弦 余弦int del_x = qCos(qDegreesToRadians(start_rotate_angle_ - av_angle_ * i)) *scale_text_radius_;int del_y = qSin(qDegreesToRadians(start_rotate_angle_ - av_angle_ * i)) *scale_text_radius_;// 平移坐标系painter.translate(QPoint(del_x, -del_y));// 选择坐标系painter.rotate(-kScaleAngle / 2 + av_angle_ * i);// 绘制文字painter.drawText(QRect(-min_unit_ / 2, -min_unit_ / 2, min_unit_, min_unit_),Qt::AlignCenter, QString::number(i * kOneScaleValue));// 恢复坐标painter.restore();}}painter.restore();
}void CarDashboard::drawPointer(QPainter &painter) {painter.save();painter.setPen(Qt::NoPen);painter.setBrush(Qt::white);const QPointF point[4]{QPointF(0, 0.0),QPointF(height_half_ - min_unit_ * 5 / 2, -min_unit_ / 32.0),QPointF(height_half_ - min_unit_ * 5 / 2, min_unit_ / 32.0),QPointF(0, min_unit_ / 3.0),};painter.rotate(start_rotate_angle_clock_ + av_angle_ * scale_value_);painter.drawPolygon(point, 4);painter.restore();
}void CarDashboard::drawSector(QPainter &painter) {const int radius = height_half_ + min_unit_ / 2;painter.save();painter.setPen(Qt::NoPen);painter.setBrush(QColor(255, 0, 0, 50));QRect rect(-radius, -radius, radius * 2, radius * 2);painter.drawPie(rect, start_rotate_angle_ * 16,-av_angle_ * scale_value_ * 16);painter.restore();
}void CarDashboard::drawInnerShine(QPainter &painter) {painter.setBrush(QColor(255, 0, 0, 150));painter.drawEllipse(QPoint(0, 0), min_unit_ * 2, min_unit_ * 2);
}void CarDashboard::drawInnerBlack(QPainter &painter) {painter.setBrush(Qt::black);painter.drawEllipse(QPoint(0, 0), min_unit_ * 3 / 2, min_unit_ * 3 / 2);
}void CarDashboard::drawCurrentValue(QPainter &painter) {painter.setPen(QPen(Qt::white, 3));QFont font("Arial", font_size_ * 3 / 2);font.setBold(true);painter.setFont(font);painter.drawText(QRect(-min_unit_, -min_unit_, min_unit_ * 2, min_unit_),Qt::AlignCenter,QString::number(scale_value_ * kOneScaleValue));font.setPointSize(font_size_ * 3 / 4);painter.setFont(font);painter.drawText(QRect(-min_unit_, min_unit_ / 2, min_unit_ * 2, min_unit_ / 2),Qt::AlignCenter, "Km/h");
}void CarDashboard::paintEvent(QPaintEvent *event) {Q_UNUSED(event);QPainter painter(this);// 初始化画布initCanvas(painter);// 画外圈渐变色drawOutterShine(painter);// 画刻度drawScale(painter);// 写刻度文字drawScaleText(painter);// 画指针drawPointer(painter);// 画扇形drawSector(painter);// 画内圈渐变色drawInnerShine(painter);// 画黑色内圈drawInnerBlack(painter);// 当前值drawCurrentValue(painter);
}
5、难点
这里难点使用正弦和余弦计算绘制刻度字。
对你有用就点个赞👍,以后需要用到就收藏⭐