Qtpainter练手项目:仪表盘相关的坐标变换与绘图
本项目实现了一个基于Qt的动态速度表盘,使用QPainter进行图形绘制。主要功能包括:动态速度指针(0-240 km/h)、渐变色彩背景、精确刻度显示、高速警告区域以及中央数值显示。核心技术点涉及坐标系变换、三角函数计算刻度位置、径向渐变效果和定时器控制的指针动画。项目通过保存/恢复坐标系状态、抗锯齿渲染等技术优化绘制效果。代码结构清晰,包含画布初始化、刻度绘制、指针动画等模块。项目地址:htt
·
Qtpainter练手项目:仪表盘相关的坐标变换与绘图
项目概述
本项目实现了一个动态速度表盘,使用Qt的QPainter进行绘制。表盘具有以下特点:
- 动态变化的速度指针(0-240 km/h范围)
- 渐变色彩的表盘背景
- 精确的刻度显示和数值标注
- 红色警告区域(高速区域)
- 中央显示当前速度值和单位
github仓库地址:https://github.com/1024freedom/Qt_dashboard
作为练习写的,还有很多值得优化的地方,欢迎交流学习
核心技术点解析
1. 坐标系变换基础
在Qt绘图中,坐标系变换是实现复杂图形绘制的关键。本项目大量使用了坐标系平移和旋转:
painter.translate(rect().center()); // 将原点移动到窗口中心
painter.rotate(135); // 旋转坐标系135度
2. 刻度值坐标变换详解
刻度值的坐标变换是本项目最复杂的部分,涉及到三角函数和坐标系变换:
// 计算每个刻度之间的角度
double angle = 270.0 / 60.0;
// 循环绘制60个刻度
for (int i = 0; i <= 60; i++) {
if (i % 5 == 0) { // 每5个刻度绘制一个数值
// 计算当前刻度相对于零点的角度(取模45度)
angle_move = fmod(angle * i, 45.0);
// 使用三角函数计算圆周上的坐标
x = cos(angle_move) * r;
y = sin(angle_move) * r;
// 计算到原点的距离(用于平移坐标系)
targetX = sqrt(x * x + y * y);
// 保存当前坐标系状态
painter.save();
// 将坐标系平移到刻度位置
painter.translate(targetX, 0);
// 旋转文本使其与圆周切线方向一致
painter.rotate(90);
// 绘制刻度数值
painter.drawText(-10, 4, QString::number(i * 4));
// 恢复坐标系状态
painter.restore();
// 绘制主刻度线
painter.drawLine(height() / 2 - 15, 0, height() / 2 - 1, 0);
} else {
// 绘制次刻度线
painter.drawLine(height() / 2 - 6, 0, height() / 2 - 1, 0);
}
// 旋转坐标系为下一个刻度做准备
painter.rotate(angle);
}
坐标变换原理:
- 首先将坐标系旋转135度,使0刻度位于左下方
- 对于每个主刻度,计算其在圆周上的位置
- 以仪表盘中心为坐标原点,水平向右为x轴正方向建立平面直角坐标系,通过三角函数来获取目标刻度位置的坐标(注意传统的直角坐标系与qt坐标系的区别)
- 通过
translate()
将坐标系移动到刻度位置 - 旋转文本使其与圆周切线方向一致
- 绘制文本后恢复坐标系状态
3. 渐变效果实现
项目中使用径向渐变创建了表盘的立体效果:
// 表盘外部光圈渐变
QRadialGradient radialGradient0(0, 0, height() / 2 + 25);
radialGradient0.setColorAt(0.85, QColor(Qt::black));
radialGradient0.setColorAt(1.0, QColor(Qt::red));
// 表盘背景渐变
QRadialGradient radialGradient(0, 0, height() / 2);
radialGradient.setColorAt(0.0, QColor(Qt::gray));
radialGradient.setColorAt(1.0, QColor(Qt::black));
4. 指针动态效果
指针的动态旋转通过定时器控制:
// 定时器控制速度值变化
connect(timer, &QTimer::timeout, this, [ = ]() {
if (flag) {
currentValue--;
if (currentValue <= 0) flag = false;
} else {
currentValue++;
if (currentValue >= 60) flag = true;
}
update(); // 触发重绘
});
// 绘制指针时应用旋转
painter.rotate(135 + currentValue * angle);
5. 扇形绘制技巧
使用drawPie()
方法绘制速度表盘的扇形区域:
painter.drawPie(QRect(-r / 2 + 60, -r / 2 + 60, r - 120, r - 120),
(-135) * 16, -angle * currentValue * 16);
参数说明:
- 第一个参数定义扇形的外接矩形
- 第二个参数是起始角度(注意qt以1/16度作为基本单位)
- 第三个参数是扇形跨度角度
完整代码结构
项目的主要绘制逻辑分布在以下几个方法中:
initCanvas()
- 初始化画布和表盘背景drawMiddleCircle()
- 绘制中央小圆drawGradation()
- 绘制刻度和数值drawPointer()
- 绘制指针draw_Pie()
- 绘制扇形区域drawEllipseInnerBlack()
和drawEllipseInnerShine()
- 绘制中央区域效果drawMiddleValue()
- 绘制中央数值显示
开发小技巧与注意事项
- 状态保存与恢复:使用
save()
和restore()
管理坐标系状态,避免变换累积 - 抗锯齿渲染:使用
setRenderHint(QPainter::Antialiasing, true)
提高绘制质量 - 性能优化:在
paintEvent
中避免频繁创建和销毁对象 - 坐标系统一:所有绘图操作基于以窗口中心为原点的坐标系
还有很多需要优化的地方 欢迎交流学习!
更多推荐
所有评论(0)