使用 Qt 实现自定义罗盘控件

用 Qt 编写一个简单的罗盘控件,该控件能够动态显示方向。该控件实现了一个带有北(N)和南(S)标记的圆形罗盘面盘,具有可以根据输入角度旋转的指针。

代码功能概述

该项目定义了一个 CompassWidget 类,继承自 QWidget,实现了如下功能:

  1. 绘制罗盘的背景和刻度线。
  2. 显示北(N)和南(S)方向标记。
  3. 根据输入角度旋转指针,显示指定方向。

核心代码结构

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(指向正北),并设置控件的最小尺寸为 200x200setAngle 方法用于更新角度,并通过 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);
  1. 设置绘制区域 :确保罗盘始终居中显示,使用 setViewportsetWindow 设置绘图区域。

  2. 绘制背景

    cpp 复制代码
    painter.setBrush(Qt::blue);
    painter.setPen(Qt::NoPen);
    painter.drawEllipse(-100, -100, 200, 200);

    使用 drawEllipse 绘制一个蓝色圆形背景作为罗盘盘面。

  3. 绘制刻度线

    cpp 复制代码
    painter.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) 用于在绘制每条刻度后旋转坐标系。

  4. 绘制"N"和"S"标记

    cpp 复制代码
    QFont 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" 以指示北和南的方向。

  5. 绘制罗盘针

    cpp 复制代码
    painter.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) 方法根据输入的角度旋转画布。
    • 绘制指针:指针分为白色的南针部分和红色的北针部分,使用三角形绘制两个箭头形状的针头。
  6. 恢复坐标系

    cpp 复制代码
    painter.resetTransform();

    最后,重置坐标系,以确保下一次重绘时从初始状态开始。

总结

通过这段代码,我们成功创建了一个自定义罗盘控件,具备动态旋转指针的功能。此控件非常适合用于导航应用或其他需要展示方向的场景。Qt 的 QPainterQWidget 的灵活性,使得我们可以轻松绘制出各种形状和动态效果,从而创建出更复杂的图形控件。

相关推荐
Algorithm15765 分钟前
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
开发语言·云原生·golang
shinelord明15 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
Monly2121 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
boligongzhu22 分钟前
DALSA工业相机SDK二次开发(图像采集及保存)C#版
开发语言·c#·dalsa
Eric.Lee202122 分钟前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
7yewh25 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
waicsdn_haha36 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
_WndProc38 分钟前
C++ 日志输出
开发语言·c++·算法
qq_433554541 小时前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
数据小爬虫@1 小时前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python