用 Qt 编写一个简单的罗盘控件,该控件能够动态显示方向。该控件实现了一个带有北(N)和南(S)标记的圆形罗盘面盘,具有可以根据输入角度旋转的指针。
代码功能概述
该项目定义了一个 CompassWidget
类,继承自 QWidget
,实现了如下功能:
- 绘制罗盘的背景和刻度线。
- 显示北(N)和南(S)方向标记。
- 根据输入角度旋转指针,显示指定方向。
核心代码结构
CompassWidget.h
首先,CompassWidget.h
定义了罗盘控件的接口,包括一个设置角度的方法和一个用于自定义绘制的 paintEvent
函数。
cpp
#ifndef COMPASSWIDGET_H
#define COMPASSWIDGET_H
#include <QWidget>
class CompassWidget : public QWidget
{
Q_OBJECT
public:
explicit CompassWidget(QWidget *parent = nullptr);
void setAngle(double newAngle); // 设置指针角度
protected:
void paintEvent(QPaintEvent *event) override; // 自定义绘制
private:
double angle; // 以度为单位的角度,正北为0度,顺时针增加
};
#endif // COMPASSWIDGET_H
代码实现详解
初始化和设置角度
在 CompassWidget.cpp
中,我们定义了构造函数和设置角度的方法。构造函数设置了默认角度 0
(指向正北),并设置控件的最小尺寸为 200x200
。setAngle
方法用于更新角度,并通过 update()
触发重绘。
cpp
#include "CompassWidget.h"
#include <QPainter>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
CompassWidget::CompassWidget(QWidget *parent) : QWidget(parent), angle(0)
{
setMinimumSize(200, 200);
}
void CompassWidget::setAngle(double newAngle)
{
angle = newAngle;
update(); // 重新绘制小部件
}
自定义绘制逻辑:paintEvent
paintEvent
是 Qt 中用于自定义绘制的事件处理函数。该函数中包含绘制罗盘的所有细节,包括背景、刻度线、方向标记和指针。
cpp
void CompassWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); // 开启抗锯齿
int side = qMin(width(), height());
// 保持图形居中
painter.setViewport((width() - side) / 2, (height() - side) / 2, side, side);
painter.setWindow(-100, -100, 200, 200);
-
设置绘制区域 :确保罗盘始终居中显示,使用
setViewport
和setWindow
设置绘图区域。 -
绘制背景:
cpppainter.setBrush(Qt::blue); painter.setPen(Qt::NoPen); painter.drawEllipse(-100, -100, 200, 200);
使用
drawEllipse
绘制一个蓝色圆形背景作为罗盘盘面。 -
绘制刻度线:
cpppainter.setPen(QPen(Qt::white, 1)); for (int i = 0; i < 360; i += 6) { if (i % 30 == 0) { painter.drawLine(90, 0, 100, 0); } else { painter.drawLine(95, 0, 100, 0); } painter.rotate(6); }
每隔
6
度绘制一个刻度线,每隔30
度绘制一个较长的刻度,表示主要方向。rotate(6)
用于在绘制每条刻度后旋转坐标系。 -
绘制"N"和"S"标记:
cppQFont font = painter.font(); font.setBold(true); font.setPointSize(10); painter.setFont(font); painter.setPen(Qt::white); painter.drawText(-5, -75, "N"); painter.drawText(-5, 85, "S");
在罗盘上部和下部分别绘制 "N" 和 "S" 以指示北和南的方向。
-
绘制罗盘针:
cpppainter.translate(0, 0); painter.rotate(angle); // 根据角度旋转画布 painter.setBrush(Qt::black); painter.drawEllipse(-8, -8, 16, 16); // 中心小圆 // 白色南针 painter.setPen(Qt::NoPen); painter.setBrush(Qt::white); QPointF southNeedle[3] = { QPointF(-8, 10), QPointF(0, 80), QPointF(8, 10) }; painter.drawConvexPolygon(southNeedle, 3); // 红色北针 painter.setBrush(Qt::red); QPointF northNeedle[3] = { QPointF(-8, -10), QPointF(0, -80), QPointF(8, -10) }; painter.drawConvexPolygon(northNeedle, 3);
- 旋转画布 :使用
rotate(angle)
方法根据输入的角度旋转画布。 - 绘制指针:指针分为白色的南针部分和红色的北针部分,使用三角形绘制两个箭头形状的针头。
- 旋转画布 :使用
-
恢复坐标系:
cpppainter.resetTransform();
最后,重置坐标系,以确保下一次重绘时从初始状态开始。
总结
通过这段代码,我们成功创建了一个自定义罗盘控件,具备动态旋转指针的功能。此控件非常适合用于导航应用或其他需要展示方向的场景。Qt 的 QPainter
和 QWidget
的灵活性,使得我们可以轻松绘制出各种形状和动态效果,从而创建出更复杂的图形控件。