汽车仪表盘作为车辆信息交互的核心界面,需要兼具实时性、美观性和稳定性。Qt框架凭借其跨平台特性、丰富的图形库和高效的开发流程,成为此类项目的理想选择。本文将以Qt的QGraphics框架和QPointer智能指针为核心,探讨汽车仪表盘的开发流程与关键技术。
Qt提供了两种主流的图形开发方案:
void Speedometer::paintEvent(QPaintEvent* event) {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); // 反走样优化锯齿
// 绘制背景圆弧
painter.setPen(QPen(Qt::gray, 5));
painter.drawArc(rect(), 45*16, 270*16);
// 绘制动态指针
painter.setPen(QPen(Qt::red, 3));
painter.rotate(currentSpeed * angleStep); // 角度计算
painter.drawLine(center, pointerTip);
}
QPointer是一种针对QObject派生类的弱引用智能指针,主要功能包括:
QPointer<QGraphicsTextItem> warningLabel = new QGraphicsTextItem("Low Fuel!");
scene->addItem(warningLabel);
// 当燃油恢复时安全删除
if (!warningLabel.isNull()) {
delete warningLabel; // QPointer自动置空
}
通过Qt的图形框架与QPointer的协同使用,开发者不仅能实现高性能、高定制化的汽车仪表盘界面,还能有效规避资源管理中的常见风险。未来可结合OpenGL进一步提升3D渲染效果,或集成CAN总线协议实现真实车辆数据对接。
#ifndef CARDASHBOARD_H
#define CARDASHBOARD_H
#include
#include
#include
#include
class CarDashboard : public QWidget
{
Q_OBJECT
public:
CarDashboard(QWidget *parent = nullptr);
~CarDashboard();
protected:
void paintEvent(QPaintEvent *event) override;
private:
void initDashboard(QPainter &painter);
void drawMidCircle(QPainter &painter,int radius);
void drawScaleLine(QPainter& painter, int radius);
void drawScaleValue(QPainter &painter, int radius);
void drawPoint(QPainter &painter, int radius);
void drawSector(QPainter &painter, int radius);
void drawInnerEllipse(QPainter& painter, int radius);
void drawInnerEllipseBlack(QPainter& painter, int radius);
void drawCurrentSpeed(QPainter& painter);
void drawEllipseOutSkirts(QPainter& painter, int radius);
void drawLogo(QPainter& painter, int radius);
int m_startAngle;//起始角度
double m_angle1;//转速盘每个刻度角度
double m_angle2;//车速盘每个刻度角度
int m_currentValue;//车速当前值
double m_currentSpeedValue;//转速当前值
QTimer m_timer;
bool m_flag;//指针转动标志位
};
#endif // CARDASHBOARD_H
#include "cardashboard.h"
#include
#include
#include
CarDashboard::CarDashboard(QWidget *parent)
: QWidget(parent)
{
// 设置窗口标题和大小
setWindowTitle("汽车仪表盘");
resize(1200, 400);
m_startAngle = 150;
m_currentValue = 0;
m_currentSpeedValue = 0;
m_flag = true;
QPushButton *startButton = new QPushButton("启动",this);
connect(startButton,&QPushButton::clicked,this,[=](){
m_timer.start(50);
});
startButton->setGeometry(width() / 2,height()/2,50,50);
connect(&m_timer,&QTimer::timeout,[=](){
if(m_flag){
m_currentValue++;
if(m_currentValue % 2==0)
m_currentSpeedValue++;
if(m_currentValue >= 61 || m_currentSpeedValue>=40){
m_flag = false;
m_currentSpeedValue=40;
}
}
else{
m_currentValue--;
if(m_currentValue % 2==0)
m_currentSpeedValue--;
if( m_currentValue== 0){
m_flag = true;
m_currentSpeedValue=0;
}
}
//刷新控件
update();
});
}
CarDashboard::~CarDashboard()
{
}
void CarDashboard::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
int dashBoad_r = height()/2;//仪表盘半径
initDashboard(painter);
drawMiddleCircle(painter,60);
drawScaleLine(painter, dashBoad_r);
drawScaleValue(painter, dashBoad_r);
drawPoint(painter, dashBoad_r);
drawSector(painter, dashBoad_r+25);
drawInnerEllipse(painter, 110);
drawInnerEllipseBlack(painter, 80);
drawCurrentSpeed(painter);
drawEllipseOutSkirts(painter, dashBoad_r+25);
drawLogo(painter, dashBoad_r);
}
//初始化仪表盘背景及画笔样式
void CarDashboard::initDashboard(QPainter &painter)
{
//消除锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//设置底色
painter.setBrush(QColor(0,0,0));
//绘制矩形
painter.drawRect(rect());
}
//绘制中心小圆
void CarDashboard::drawMiddleCircle(QPainter &painter, int radius)
{
//设置画笔颜色和宽度
painter.setPen(QPen(QColor(255,255,255),3));
//设置中心坐标点
int cw = rect().width()/2;
QPoint center(cw / 2, rect().height()*0.7);
//平移坐标点
painter.translate(center);
//原点坐标(0,0)绘制半径为radius的圆
painter.drawEllipse(QPoint(0,0), radius, radius);
center.setX(cw);
center.setY(0);
painter.translate(center);
painter.drawEllipse(QPoint(0,0), radius, radius);
}
//绘制仪表盘
void CarDashboard::drawScaleLine(QPainter &painter, int radius)
{
//总计60个小刻度,每一个小刻度的角度值
m_angle2 = 240 * 1.0 / 60;
//保存当前坐标
painter.save();
painter.setPen(QPen(Qt::white, 5));
//设置起始刻度位置
painter.rotate(m_startAngle);
for(int i=0; i <= 60; i++){
if(i >=40 )
painter.setPen(QPen(Qt::yellow, 5));//第40个刻度后,绘制画笔修改成黄色
if(i % 5 == 0)
painter.drawLine(radius-20, 0, radius-3, 0);//绘制长刻度
else
painter.drawLine(radius-8, 0, radius-3, 0);//绘制短刻度
//绘制完一个刻度旋转一次坐标
painter.rotate(m_angle2);
}
//恢复坐标
painter.restore();
painter.setPen(QPen(Qt::white, 5));
//定位转速盘坐标原点
QPoint center(-rect().width()/2, 0);
painter.translate(center);
m_angle1 = 240 * 1.0 / 40;
//保存当前坐标
painter.save();
painter.setPen(QPen(Qt::white, 5));
//设置起始刻度位置
painter.rotate(m_startAngle);
for(int i=0; i <= 40; i++){
if(i >=25 )
painter.setPen(QPen(Qt::red, 5));//第25个刻度后,绘制画笔修改成红色
if(i % 5 == 0)
painter.drawLine(radius-20, 0, radius-3, 0);//绘制长刻度
else
painter.drawLine(radius-8, 0, radius-3, 0);//绘制短刻度
//绘制完一个刻度旋转一次坐标
painter.rotate(m_angle1);
}
//恢复坐标
painter.restore();
painter.setPen(QPen(Qt::white, 5));
}
//绘制刻度值
void CarDashboard::drawScaleValue(QPainter &painter, int radius)
{
//设置字体类型和大小
QFont textFont("Arial",15);
//设置粗体
textFont.setBold(true);
painter.setFont(textFont);
int text_r = radius - 49;
//转速盘
for(int i = 0; i <=40; i++)
{
if(i % 5 == 0)
{
if(i>=25)
painter.setPen(QPen(Qt::red, 5));
//保存当前坐标系
painter.save();
int delX = qCos((210-m_angle1*i)*M_PI/180) * text_r;
int delY = qSin(qDegreesToRadians(210-m_angle1*i)) * text_r;
//平移坐标系
painter.translate(QPoint(delX,-delY));
//旋转坐标系
painter.rotate(-120+m_angle1*i);
//写上刻度值,文字居中
painter.drawText(-25,-25,50,30,Qt::AlignCenter,QString::number(i/5));
//恢复坐标系
painter.restore();
}
}
painter.setPen(QPen(Qt::white, 5));
//定位车速盘坐标原点
QPoint center(rect().width()/2, 0);
painter.translate(center);
//车速盘
for(int i = 0; i <=60; i++)
{
if(i % 5 == 0)
{
if(i>=40)
painter.setPen(QPen(Qt::yellow, 5));
//保存当前坐标系
painter.save();
int delX = qCos((210-m_angle2*i)*M_PI/180) * text_r;
int delY = qSin(qDegreesToRadians(210-m_angle2*i)) * text_r;
//平移坐标系
painter.translate(QPoint(delX,-delY));
//旋转坐标系
painter.rotate(-120+m_angle2*i);
//写上刻度值,文字居中
painter.drawText(-25,-25,50,30,Qt::AlignCenter,QString::number(i*4));
//恢复坐标系
painter.restore();
}
}
painter.setPen(QPen(Qt::white, 5));
}
//绘制指针
void CarDashboard::drawPoint(QPainter &painter, int radius)
{
//保存当前坐标
painter.save();
//设置画刷颜色
painter.setBrush(Qt::white);
//设置画笔为无线条
painter.setPen(Qt::NoPen);
static const QPointF points[4] = {
QPointF(0, 0.0),
QPointF(radius*2.0/3, -1.1),
QPointF(radius*2.0/3, 1.1),
QPointF(0, 15.0)
};
//坐标选旋转
painter.rotate(m_startAngle + m_angle2 * m_currentValue);
//绘制多边形
painter.drawPolygon(points, 4);
//恢复坐标
painter.restore();
//定位转速盘坐标原点
QPoint center(-rect().width()/2, 0);
painter.translate(center);
painter.save();
painter.setBrush(Qt::white);
painter.setPen(Qt::NoPen);
painter.rotate(m_startAngle + m_angle1 * m_currentSpeedValue);
painter.drawPolygon(points, 4);
painter.restore();
}
//画扇形
void CarDashboard::drawSector(QPainter &painter, int radius)
{
//定义矩形区域
QRect rentangle(-radius, -radius, radius*2, radius*2);
//设置画笔无线条
painter.setPen(Qt::NoPen);
//设置画刷颜色
painter.setBrush(QColor(255,0,0,80));
//绘制扇形
painter.drawPie(rentangle, (360-m_startAngle)*16, -m_angle1 * m_currentSpeedValue*16);
painter.setBrush(QColor(170,170,0,80));
QPoint center(rect().width()/2, 0);
painter.translate(center);
painter.drawPie(rentangle, (360-m_startAngle)*16, -m_angle2 * m_currentValue*16);
}
// 画渐变内圆
void CarDashboard::drawInnerEllipse(QPainter &painter, int radius)
{
QRadialGradient radial(0,0,radius);
//中心颜色
radial.setColorAt(0.0,QColor(255,170,0,200));
//外围颜色
radial.setColorAt(1.0,QColor(0,0,0,100));
//设置画刷渐变色
painter.setBrush(radial);
//画圆形
painter.drawEllipse(QPoint(0,0), radius, radius);
QPoint center(-rect().width()/2, 0);
painter.translate(center);
painter.drawEllipse(QPoint(0,0), radius, radius);
}
// 画黑色内圈
void CarDashboard::drawInnerEllipseBlack(QPainter &painter, int radius)
{
//设置画刷
painter.setBrush(Qt::black);
//绘制圆形
painter.drawEllipse(QPoint(0,0), radius, radius);
QPoint center(rect().width()/2, 0);
painter.translate(center);
painter.drawEllipse(QPoint(0,0), radius, radius);
}
//绘制当前数值
void CarDashboard::drawCurrentSpeed(QPainter &painter)
{
painter.setPen(Qt::white);
//绘制数值
QFont font("Arial", 28);
font.setBold(true);
painter.setFont(font);
if(m_currentValue>40)
painter.setPen(Qt::yellow);
painter.drawText(QRect(-60,-60,120,70),Qt::AlignCenter,QString::number(m_currentValue*4));
//绘制单位
QFont font_u("Arial", 13);
painter.setFont(font_u);
painter.drawText(QRect(-60,-60,120,160),Qt::AlignCenter,"km/h");
QPoint center(-rect().width()/2, 0);
painter.translate(center);
painter.setFont(font);
if(m_currentSpeedValue>25)
painter.setPen(Qt::red);
painter.drawText(QRect(-60,-60,120,70),Qt::AlignCenter,QString::number(m_currentSpeedValue/5*1000));
painter.setFont(font_u);
painter.drawText(QRect(-60,-60,120,160),Qt::AlignCenter,"1000/min");
}
// 画外壳,发光外圈
void CarDashboard::drawEllipseOutSkirts(QPainter &painter, int radius)
{
//设置扇形绘制区域
QRect outAngle(-radius, -radius, 2*radius, 2*radius);
painter.setPen(Qt::NoPen);
//设置渐变色
QRadialGradient radia(0,0,radius);
radia.setColorAt(1,QColor(255,0,0,200));
radia.setColorAt(0.97,QColor(255,0,0,120));
radia.setColorAt(0.9,QColor(0,0,0,0));
radia.setColorAt(0,QColor(0,0,0,0));
painter.setBrush(radia);
//绘制圆形
painter.drawPie(outAngle,(360-150)*16,-m_angle1*61*16);
QPoint center(rect().width()/2, 0);
painter.translate(center);
radia.setColorAt(1,QColor(255,170,0,200));
radia.setColorAt(0.97,QColor(255,170,0,120));
radia.setColorAt(0.9,QColor(0,0,0,0));
radia.setColorAt(0,QColor(0,0,0,0));
painter.setBrush(radia);
painter.drawPie(outAngle,(360-150)*16,-m_angle2*61*16);
}
// 画LOGO
void CarDashboard::drawLogo(QPainter &painter, int radius)
{
//定义Logo绘制区域
QRect rectLogo(-30,radius*0.38,50,50);
painter.drawPixmap(rectLogo,QPixmap("./logo.png"));
QPoint center(-rect().width()/2, 0);
painter.translate(center);
painter.drawPixmap(rectLogo,QPixmap("./logo.png"));
}