有趣的网站官网云服务器管理
Qt学习优化的一款汽车仪表控件,根据github上面开源的进行优化,主要使用QPainter实现的一款炫酷仪表盘,其中的渐变效果比较有感觉
实现结果
仪表盘
实现源码
h文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPixmap>
#include <QTimer>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();protected:void paintEvent(QPaintEvent *event) override;void resizeEvent(QResizeEvent *event) override;private:Ui::Widget *ui;QTimer *timer;QPixmap cachedBackground;bool backgroundDirty;// 仪表盘参数const int MAX_SPEED = 240; // 最大速度const int START_ANGLE = 150; // 起始角度const int ANGLE_SPAN = 240; // 角度跨度const int WARNING_THRESHOLD = 40; // 警告阈值(刻度值)int currentValue; // 当前值(0-60)int mark; // 标记递增或递减double angle; // 每个刻度角度void startSpeed();void initCanvas(QPainter& painter);void drawMiddleCircle(QPainter &painter, int radius);void drawCurrentSpeed(QPainter &painter);void drawScale(QPainter &painter, int radius);void drawScaleText(QPainter &painter, int radius);void drawPointLine(QPainter &painter, int length);void drawSpeedArc(QPainter &painter, int radius);void drawEllipseInnerBlack(QPainter &painter, int radius);void drawEllipseInnerGlow(QPainter &painter, int radius);void drawOuterRing(QPainter &painter, int radius);void drawLogo(QPainter &painter, int radius);void drawTechCircles(QPainter &painter, int radius);void drawWarningEffect(QPainter &painter, int radius);
};
#endif // WIDGET_H
c文件
#include "widget.h"
#include "ui_widget.h"#include <QPainter>
#include <QTimer>
#include <QtMath>
#include <QEasingCurve>
#include <QResizeEvent>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), backgroundDirty(true)
{ui->setupUi(this);setFixedSize(800, 600);mark = 0;currentValue = 0;angle = ANGLE_SPAN * 1.0 / (MAX_SPEED / 4); // 计算每个刻度角度startSpeed();
}Widget::~Widget()
{delete ui;
}void Widget::startSpeed()
{timer = new QTimer(this);connect(timer, &QTimer::timeout, this, [=](){if (mark == 0) {currentValue = qMin(currentValue + 1, MAX_SPEED/4);mark = (currentValue >= MAX_SPEED/4) ? 1 : 0;} else {currentValue = qMax(currentValue - 1, 0);mark = (currentValue == 0) ? 0 : 1;}// 当接近警告阈值时刷新效果if (currentValue >= WARNING_THRESHOLD - 5 && currentValue <= WARNING_THRESHOLD + 5) {backgroundDirty = true;}update();});timer->start(50);
}void Widget::paintEvent(QPaintEvent *event)
{QPainter painter(this);// 只在需要时重绘背景if (backgroundDirty) {cachedBackground = QPixmap(size());cachedBackground.fill(Qt::transparent);QPainter bgPainter(&cachedBackground);int radius = height()/2;initCanvas(bgPainter);drawOuterRing(bgPainter, radius+25);drawScale(bgPainter, radius);drawScaleText(bgPainter, radius);drawTechCircles(bgPainter, radius);drawLogo(bgPainter, radius);backgroundDirty = false;}painter.drawPixmap(0, 0, cachedBackground);// 只绘制动态部分int radius = height()/2;painter.translate(rect().width()/2, rect().height()*0.6);drawSpeedArc(painter, radius+25);drawEllipseInnerGlow(painter, 110);drawEllipseInnerBlack(painter, 80);drawMiddleCircle(painter, 60);drawCurrentSpeed(painter);drawPointLine(painter, radius-58);// 警告效果if (currentValue >= WARNING_THRESHOLD) {drawWarningEffect(painter, radius+25);}
}void Widget::resizeEvent(QResizeEvent *event)
{backgroundDirty = true;QWidget::resizeEvent(event);
}void Widget::initCanvas(QPainter& painter)
{painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);// 科技感深色背景QLinearGradient gradient(0, 0, width(), height());gradient.setColorAt(0, QColor(10, 15, 30));gradient.setColorAt(1, QColor(5, 10, 20));painter.setBrush(gradient);painter.drawRect(rect());// 坐标系平移到坐标中心QPoint cent(rect().width()/2, rect().height()*0.6);painter.translate(cent);
}void Widget::drawMiddleCircle(QPainter &painter, int radius)
{painter.setPen(QPen(QColor(100, 180, 255), 3));painter.setBrush(QColor(20, 30, 50));painter.drawEllipse(QPoint(0, 0), radius, radius);// 中心小圆点painter.setPen(Qt::NoPen);painter.setBrush(QColor(100, 180, 255));painter.drawEllipse(QPoint(0, 0), 5, 5);
}void Widget::drawCurrentSpeed(QPainter &painter)
{// 主速度值QFont font("Arial", 30);font.setBold(true);painter.setFont(font);// 文字发光效果QLinearGradient textGradient(0, -60, 0, -20);textGradient.setColorAt(0, QColor(150, 220, 255));textGradient.setColorAt(1, QColor(50, 150, 255));painter.setPen(QPen(textGradient, 1));painter.drawText(QRect(-60, -60, 120, 70), Qt::AlignCenter, QString::number(currentValue*4));// 单位QFont font2("Arial", 13);font2.setBold(true);painter.setFont(font2);painter.setPen(QColor(150, 200, 255));painter.drawText(QRect(-60, -60, 120, 160), Qt::AlignCenter, "Km/h");
}void Widget::drawScale(QPainter &painter, int radius)
{painter.save();painter.rotate(START_ANGLE);for (int i = 0; i <= MAX_SPEED/4; i++) {// 设置不同颜色if (i >= WARNING_THRESHOLD) {painter.setPen(QPen(QColor(255, 80, 80), 5));} else {painter.setPen(QPen(QColor(100, 180, 255), 5));}if (i % 5 == 0) {// 长刻度线painter.drawLine(radius - 20, 0, radius - 3, 0);} else {// 短刻度线painter.drawLine(radius - 8, 0, radius - 3, 0);}painter.rotate(angle);}painter.restore();
}void Widget::drawScaleText(QPainter &painter, int radius)
{QFont font("Arial", 15);font.setBold(true);painter.setFont(font);int r = radius - 49;for (int i = 0; i <= MAX_SPEED/4; i++) {if (i % 5 == 0) {painter.save();// 计算文本位置double textAngle = 210 - angle * i;int delX = qCos(qDegreesToRadians(textAngle)) * r;int delY = qSin(qDegreesToRadians(textAngle)) * r;painter.translate(QPoint(delX, -delY));painter.rotate(-120 + angle * i);// 设置文本颜色if (i >= WARNING_THRESHOLD) {painter.setPen(QColor(255, 100, 100));} else {QLinearGradient grad(0, 0, 0, 20);grad.setColorAt(0, QColor(150, 220, 255));grad.setColorAt(1, QColor(50, 150, 255));painter.setPen(QPen(grad, 1));}painter.drawText(-25, -25, 50, 30, Qt::AlignCenter, QString::number(i*4));painter.restore();}}
}void Widget::drawPointLine(QPainter &painter, int length)
{painter.save();// 指针渐变QLinearGradient gradient(0, 0, length, 0);if (currentValue >= WARNING_THRESHOLD) {gradient.setColorAt(0, QColor(255, 150, 150));gradient.setColorAt(0.5, QColor(255, 100, 100));gradient.setColorAt(1, QColor(200, 50, 50));} else {gradient.setColorAt(0, QColor(200, 230, 255));gradient.setColorAt(0.5, QColor(100, 180, 255));gradient.setColorAt(1, QColor(50, 120, 220));}painter.setBrush(gradient);painter.setPen(Qt::NoPen);// 指针形状QPainterPath path;path.moveTo(0, 0);path.lineTo(length * 0.9, -length * 0.02);path.lineTo(length, 0);path.lineTo(length * 0.9, length * 0.02);path.closeSubpath();// 旋转并绘制指针painter.rotate(START_ANGLE + angle * currentValue);painter.drawPath(path);// 指针中心圆painter.setBrush(QColor(30, 50, 80));painter.drawEllipse(QPoint(0, 0), 10, 10);// 中心圆发光效果QRadialGradient centerGrad(0, 0, 10);centerGrad.setColorAt(0, QColor(100, 180, 255, 150));centerGrad.setColorAt(1, Qt::transparent);painter.setBrush(centerGrad);painter.drawEllipse(QPoint(0, 0), 15, 15);painter.restore();
}void Widget::drawSpeedArc(QPainter &painter, int radius)
{QRect rectangle(-radius, -radius, radius*2, radius*2);painter.setPen(Qt::NoPen);// 速度弧渐变QConicalGradient gradient(0, 0, -START_ANGLE);gradient.setColorAt(0.0, QColor(100, 200, 255, 200));gradient.setColorAt(0.5, QColor(50, 150, 255, 150));gradient.setColorAt(1.0, QColor(0, 100, 200, 100));painter.setBrush(gradient);painter.drawPie(rectangle, (360-START_ANGLE)*16, -angle*currentValue*16);// 添加发光效果QRadialGradient glow(0, 0, radius);glow.setColorAt(0, QColor(100, 180, 255, 50));glow.setColorAt(1, Qt::transparent);painter.setBrush(glow);painter.drawPie(rectangle, (360-START_ANGLE)*16, -angle*currentValue*16);
}void Widget::drawEllipseInnerBlack(QPainter &painter, int radius)
{painter.setBrush(QColor(20, 30, 50));painter.setPen(Qt::NoPen);painter.drawEllipse(QPoint(0, 0), radius, radius);
}void Widget::drawEllipseInnerGlow(QPainter &painter, int radius)
{QRadialGradient gradient(0, 0, radius);gradient.setColorAt(0.0, QColor(100, 180, 255, 150));gradient.setColorAt(0.5, QColor(50, 120, 220, 100));gradient.setColorAt(1.0, QColor(0, 50, 100, 50));painter.setBrush(gradient);painter.setPen(Qt::NoPen);painter.drawEllipse(QPoint(0, 0), radius, radius);
}void Widget::drawOuterRing(QPainter &painter, int radius)
{QRect rectangle(-radius, -radius, radius*2, radius*2);painter.setPen(Qt::NoPen);// 外环渐变QRadialGradient gradient(0, 0, radius);gradient.setColorAt(1.0, QColor(50, 150, 255, 150));gradient.setColorAt(0.97, QColor(50, 150, 255, 50));gradient.setColorAt(0.9, Qt::transparent);gradient.setColorAt(0, Qt::transparent);painter.setBrush(gradient);painter.drawPie(rectangle, (360-START_ANGLE)*16, -angle*(MAX_SPEED/4)*16);// 外环边缘painter.setPen(QPen(QColor(100, 180, 255, 100), 2));painter.setBrush(Qt::NoBrush);painter.drawArc(rectangle, (360-START_ANGLE)*16, -angle*(MAX_SPEED/4)*16);
}void Widget::drawLogo(QPainter &painter, int radius)
{QRect rectangle(-65, radius*0.38, 130, 50);// 绘制logo背景painter.setPen(QPen(QColor(100, 180, 255, 100), 1));painter.setBrush(QColor(0, 0, 0, 100));painter.drawRoundedRect(rectangle, 5, 5);// 绘制logo图片painter.drawPixmap(rectangle, QPixmap(":/icon.png"));
}void Widget::drawTechCircles(QPainter &painter, int radius)
{// 绘制科技感同心圆painter.setPen(QPen(QColor(50, 150, 255, 30), 1));painter.setBrush(Qt::NoBrush);for (int i = 1; i <= 5; i++) {int r = radius * 0.2 * i;painter.drawEllipse(QPoint(0, 0), r, r);}// 绘制径向线for (int i = 0; i < 360; i += 15) {painter.save();painter.rotate(i);painter.drawLine(QPoint(0, 0), QPoint(radius, 0));painter.restore();}
}void Widget::drawWarningEffect(QPainter &painter, int radius)
{static int alpha = 0;static bool increasing = true;// 更新alpha值if (increasing) {alpha += 10;if (alpha >= 80) increasing = false;} else {alpha -= 10;if (alpha <= 20) increasing = true;}// 绘制蓝色闪烁效果painter.setPen(Qt::NoPen);painter.setBrush(QColor(100, 150, 255, alpha));painter.drawEllipse(QPoint(0, 0), radius, radius);
}
希望对大家有所帮助