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

news2024/11/8 11:00:33

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

代码功能概述

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

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

在这里插入图片描述

核心代码结构

CompassWidget.h

首先,CompassWidget.h 定义了罗盘控件的接口,包括一个设置角度的方法和一个用于自定义绘制的 paintEvent 函数。

#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() 触发重绘。

#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 中用于自定义绘制的事件处理函数。该函数中包含绘制罗盘的所有细节,包括背景、刻度线、方向标记和指针。

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. 绘制背景

    painter.setBrush(Qt::blue);
    painter.setPen(Qt::NoPen);
    painter.drawEllipse(-100, -100, 200, 200);
    

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

  3. 绘制刻度线

    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”标记

    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. 绘制罗盘针

    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. 恢复坐标系

    painter.resetTransform();
    

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

总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2228478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法|牛客网华为机试21-30C++

牛客网华为机试 上篇&#xff1a;算法|牛客网华为机试10-20C 文章目录 HJ21 简单密码HJ22 汽水瓶HJ23 删除字符串中出现次数最少的字符HJ24 合唱队HJ25 数据分类处理HJ26 字符串排序HJ27 查找兄弟单词HJ28 素数伴侣HJ29 字符串加解密HJ30 字符串合并处理 HJ21 简单密码 题目描…

使用 MMDetection 实现 Pascal VOC 数据集的目标检测项目练习(二) ubuntu的下载安装

首先&#xff0c;Linux系统是人工智能和深度学习首选系统。原因如下: 开放性和自由度&#xff1a;Linux 是一个开源操作系统&#xff0c;允许开发者自由修改和分发代码。这在开发和研究阶段非常有用&#xff0c;因为开发者可以轻松地访问和修改底层代码。社区支持&#xff1a;…

【ECMAScript标准】深入解析ES5:现代JavaScript的基石

&#x1f9d1;‍&#x1f4bc; 一名茫茫大海中沉浮的小小程序员&#x1f36c; &#x1f449; 你的一键四连 (关注 点赞收藏评论)是我更新的最大动力❤️&#xff01; &#x1f4d1; 目录 &#x1f53d; 前言1️⃣ ES5的概述2️⃣ ES5的关键特性3️⃣ ES5与之前版本的区别4️⃣ …

【万户软件-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

第2章 Android App开发基础

第 2 章 Android App开发基础 bilibili学习地址 github代码地址 本章介绍基于Android系统的App开发常识&#xff0c;包括以下几个方面&#xff1a;App开发与其他软件开发有什么不一 样&#xff0c;App工程是怎样的组织结构又是怎样配置的&#xff0c;App开发的前后端分离设计…

文本分段Chunking综述-RAG

为什么要分段&#xff1f; 即便大模型开始普通支持更大的上下文&#xff0c;但 RAG 技术目前仍然具有不可替代的价值&#xff0c;RAG 需要外部知识库。外部知识文档往往比较长&#xff0c;可能是包含几十页甚至数百页的内容&#xff0c;如果直接使用会存在以下问题&#xff1a…

R语言 | paletteer包:拥有2100多个调色板!

看到 PMID:39024031 文章的代码中&#xff0c;有颜色设置的语句&#xff1a; pal <- paletteer_d("ggsci::category20_d3")[c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)]DimPlot(MM,reduction umap,group.by "sample",label F,pt.size 0.1,c…

怎么看AI大模型(LLM)、智能体(Agent)、知识库、向量数据库、知识图谱,RAG,AGI 的不同形态?

前言 在 AI 人工智能时代&#xff0c;智能体将会是未来最主流的大模型应用方式&#xff1f;人人都有机会通过智能体&#xff0c;解锁成为【超级个体】。 在人工智能的快速发展中&#xff0c;LLM、Agent、知识库、向量数据库、RAG&#xff08;检索增强生成&#xff09;、知识图…

照片不完整?来试试智能扩图,简直不要太满意!(不是广告)

生活中有些照片拍过之后&#xff0c;当时觉得很满意&#xff0c;但过段时间就恨当初没有拍一张完整的图片&#xff01; ——来自小白的感慨 当时跟家里的叮当一起去旅游&#xff0c;我给他拍了一张好看的照片&#xff1a; 今天这张照片如果是整图就好了&#xff01;好气哦&am…

idea连接数据库出现错误的解决方式

在使用idea连接数据库时&#xff0c;出现错误&#xff1a; The server has terminated the handshake. The protocol list option (enabledTLSProtocols) is set, this option might cause connection issues with some versions of MySQL. Consider removing the protocol li…

1. STM32环境搭建

1. MDK5(keil) 安装 安装包获取&#xff0c;可以在官网下载 https://www.keil.com/demo/eval/arm.htm 或者通过其他方式获取&#xff0c;下载 下载完有一个安装包和 “钥匙”&#xff0c;解压时关闭杀毒软件&#xff0c;防止被清理掉 1.1 安装 软件安装位置选择&#xff1a;…

map的oj题

第一题 . - 力扣&#xff08;LeetCode&#xff09; 第二题 单词识别_牛客题霸_牛客网 解题思路&#xff1a; 1&#xff0c;将数据放入set或者map中去重和更新次数, 即利用set和map的[ ] 2. 将数据放到vector 进行排序 &#xff0c;还应该利用仿函数写出 Compare() ,因为s…

Android13预置应用及授权开发

在android13中&#xff0c;要预置一个对讲应用&#xff0c;从预置和授权&#xff0c;梳理了一下&#xff0c;以便后续查询使用。在此记录 一放置应用 我的apk应用放在vendor下面&#xff0c; 路径&#xff1a;projectroot/vendor/fly/package/apps/DMR/flydmr.apk (vendor/fl…

【深度学习中的注意力机制9】11种主流注意力机制112个创新研究paper+代码——滑动窗口注意力(Sliding Window Attention)

【深度学习中的注意力机制9】11种主流注意力机制112个创新研究paper代码——滑动窗口注意力&#xff08;Sliding Window Attention&#xff09; 【深度学习中的注意力机制9】11种主流注意力机制112个创新研究paper代码——滑动窗口注意力&#xff08;Sliding Window Attention…

RK3568平台(PWM篇)红外遥控适配

一.红外遥控简介 红外遥控的发射电路是采用红外发光二极管来发出经过调制的红外光波;红外接收电路由红外 接收二极管、三极管或硅光电池组成,它们将红外发射器发射的红外光转换为相应的电信号,再送 后置放大器。 鉴于家用电器的品种多样化和用户的使用特点,生产厂家对进行…

【Linux初阶】指令操作

上一篇文章&#xff08;⭐点这里⭐⭐点这里&#xff09;我们初步对Linux有了一些基本的认识&#xff0c;了解到了Windows的图形化界面操作和Linux的纯命令指令是操作上二者最大的区别&#xff0c;今天我们来继续深入的学习Linux的操作指令&#xff0c;学习一些基本的指令来控制…

跨平台开发支付组件,实现支付宝支付

效果图&#xff1a; custom-payment &#xff1a; 在生成预付订单之后页面中需要弹出一个弹层&#xff0c;弹层中展示的内容为支付方式&#xff08;渠道&#xff09;&#xff0c;由用户选择一种支付方式进行支付。 该弹层组件是以扩展组件 uni-popup 为核心的&#xff0c;关于…

MFC图形函数学习04——画矩形函数

MFC中绘制矩形函数是MFC的基本绘图函数&#xff0c;它的大小和位置由左上角和右下角的坐标决定&#xff1b;若想绘制的矩形边框线型、线宽、颜色以及填充颜色都还需要其它函数的配合。 一、绘制矩形函数 原型&#xff1a;BOOL Rectangle(int x1,int y1,int x2,int y2); …

【网络面试篇】TCP连接建立(笔记)

目录 一、三次握手 1. 过程描述 2. 为什么是三次握手&#xff1f;不是两次、四次&#xff1f; &#xff08;1&#xff09;三次握手才可以阻止重复历史连接的初始化 &#xff08;2&#xff09;三次握手才可以同步双方的初始序列号 &#xff08;3&#xff09;三次握手才可以…

04.DDD与CQRS

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 定义职责分离DDD与CQRS的关系领域模型和查询模型特点命令场景的领域模型查询场景的查询模型 架构方案领域事件方案1&#xff1a…