QT上位机开发(图形绘制)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        图形绘制是上位机软件开发很重要的一个功能。这个图形绘制,有的是离线的,有的是实时绘制的。就我个人而言,离线绘制的情况可能更多一些,因为可以反复看、反复研究。相信做过控制的同学肯定都学过PID,用上位机调整PID参数就是很好的一种方式。今天呢,我们正好借助于qt的painter机制,来绘制一个简单的正弦图和余弦图,以备将来之用。

1、创建qt示例工程

        因为今天实现的是图形绘制,所以基本上只需要一个空窗口就可以。不需要用designer在上面绘制任何的控件。

2、QtWidgetsApplication.h头文件

        图形绘制中不涉及到任何的变量,目前只涉及到一个函数,那就是paintEvent这个函数。所以,在头文件中也只需要添加这么一个函数即可。

#pragma once#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication.h"class QtWidgetsApplication : public QMainWindow
{Q_OBJECTpublic:QtWidgetsApplication(QWidget *parent = nullptr);~QtWidgetsApplication();private:Ui::QtWidgetsApplicationClass ui;protected:void paintEvent(QPaintEvent *event);};

3、QtWidgetsApplication.cpp文件

        对于窗口,或者是widget的重绘,在qt上面都是通过paintEvent函数进行的。首先呢,一般先创建一个QPainter变量,入参就是当前的窗口。接着,绘制两条直线,分别是x轴和y轴。有了这两条轴之后,就可以接着绘制正弦和余弦了。

        因为正弦和余弦是非常类似的,所以这里仅分析一下正弦的画法。绘制正弦之前,需要确定一下采样的点数,也就是绘制的精度是多少。当然,因为整个窗口是需要画满的,这个时候总的宽度和点数相除,就产生了步进的长度。

        有了步进长度和总点数之后,就开始计算每个点的位置。此时又因为绘制y轴的时候,窗口的坐标是至上而下的,这和实际的坐标有点差别,所以需要用height/2 - v_sin*height/2处理下。每次绘制的时候,都是绘制的一条短直线,很多短的直线连在一起,构成了我们需要的正弦弧线。这就是整个绘制的过程。

#include <QtWidgets>
#include "QtWidgetsApplication.h"QtWidgetsApplication::QtWidgetsApplication(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);
}// destructor function
QtWidgetsApplication::~QtWidgetsApplication()
{
}void QtWidgetsApplication::paintEvent(QPaintEvent *event)  {Q_UNUSED(event);QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);int width = this->width();int height = this->height();// draw axispainter.drawLine(0, height / 2, width, height / 2); // Xpainter.drawLine(width / 2, 0, width / 2, height); // Yint samples = 100; // sample numberdouble step = static_cast<double>(width) / samples;// sin curvepainter.setPen(Qt::blue);QPointF lastPoint(0, height / 2 - sin(0) * height / 2);for (int i = 1; i <= samples; ++i) {double x = i * step;double y = height / 2 - sin(x / width * 4 * M_PI) * height / 2;painter.drawLine(lastPoint, QPointF(x, y));lastPoint = QPointF(x, y);}// cos curvepainter.setPen(Qt::red);lastPoint = QPointF(0, height / 2 - cos(0) * height / 2);for (int i = 1; i <= samples; ++i) {double x = i * step;double y = height / 2 - cos(x / width * 4 * M_PI) * height / 2;painter.drawLine(lastPoint, QPointF(x, y));lastPoint = QPointF(x, y);}
}

  

4、编译和测试

        编译和测试就比较简单了,如果显示没有问题,那就代表是正确的;反之,就是有问题了。具体是显示的问题,还是计算的问题,这个就要去单步debug一下才知道了。

5、动态的正弦和余弦

        上面测试的正弦和余弦虽然没有问题,但是不知道大家有没有想过,如何才能让这两组曲线动起来呢。其实,方法就在于定时器和曲线的相位,首先需要在QtWidgetsApplication.h添加变量,即定时器、phase和定时器槽函数,

#pragma once#include <QtWidgets/QMainWindow>
#include <QTimer>
#include "ui_QtWidgetsApplication.h"class QtWidgetsApplication : public QMainWindow
{Q_OBJECTpublic:QtWidgetsApplication(QWidget *parent = nullptr);~QtWidgetsApplication();private:Ui::QtWidgetsApplicationClass ui;protected:void paintEvent(QPaintEvent *event);private slots:void updateAnimation();private:QTimer *timer;double phase;
};

        做好了这一点,QtWidgetsApplication.cpp也做做出修改,相关的动作包括初始化定时器、实现定时器回调函数、根据phase重新绘制曲线。这里面需要注意的就是update函数,它会触发窗口重新绘制。

#include <QtWidgets>
#include "QtWidgetsApplication.h"QtWidgetsApplication::QtWidgetsApplication(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);timer = new QTimer(this);connect(timer, &QTimer::timeout, this, &QtWidgetsApplication::updateAnimation);timer->start(50); // timer interval is 50msphase = 0.0;
}// destructor function
QtWidgetsApplication::~QtWidgetsApplication()
{
}void QtWidgetsApplication::paintEvent(QPaintEvent *event)  {Q_UNUSED(event);QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);int width = this->width();int height = this->height();// draw axispainter.drawLine(0, height / 2, width, height / 2); // Xpainter.drawLine(width / 2, 0, width / 2, height); // Yint samples = 100; // sampledouble step = static_cast<double>(width) / samples;// draw sinpainter.setPen(Qt::blue);QPointF lastPoint(0, height / 2 - sin(phase) * height / 2);for (int i = 1; i <= samples; ++i) {double x = i * step;double y = height / 2 - sin(x / width * 4 * M_PI + phase) * height / 2;painter.drawLine(lastPoint, QPointF(x, y));lastPoint = QPointF(x, y);}// draw cospainter.setPen(Qt::red);lastPoint = QPointF(0, height / 2 - cos(phase) * height / 2);for (int i = 1; i <= samples; ++i) {double x = i * step;double y = height / 2 - cos(x / width * 4 * M_PI + phase) * height / 2;painter.drawLine(lastPoint, QPointF(x, y));lastPoint = QPointF(x, y);}
}void QtWidgetsApplication::updateAnimation() {phase += 0.1; // update phaseupdate();     // trigger painter
}

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

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

相关文章

JoySSL怎么样

JoySSL是一家专业的SSL证书服务提供商&#xff0c;致力于为网站和在线业务提供最佳的安全加密解决方案。以下是JoySSL的一些优点&#xff1a; 提供多种类型的SSL证书选择&#xff1a;JoySSL提供单域名、多域名、通配符等不同类型的SSL证书&#xff0c;以满足不同网站的需求。证…

【嵌入式】飞凌嵌入式ELF1开发板 初体验 | 嵌入式Linux开发

文章目录 前言一、开机初体验1.1、开机1.2、连接WIFI 二、基本功能测试2.1、主板命令行测试2.1.1、TF卡热插拔测试2.1.2、LED命令行测试2.1.3、数据库测试 三、基础编程实战3.1、交叉编译链部署3.2、温湿度传感器程序3.3、看门狗程序3.4、六轴传感器程序3.5、MQTT物联网 bug记录…

ROS TF坐标变换 - 动态坐标变换

目录 一、动态坐标变换&#xff08;C实现&#xff09;二、动态坐标变换&#xff08;Python实现&#xff09; 一、动态坐标变换&#xff08;C实现&#xff09; 所谓动态坐标变换&#xff0c;是指两个坐标系之间的相对位置是变化的。比如机械臂末端执行器与 base_link 之间&…

渗透线上下料控制(SCL源代码)

有关渗透线的其它详细介绍请参考下面链接文章&#xff1a; https://rxxw-control.blog.csdn.net/article/details/133611151https://rxxw-control.blog.csdn.net/article/details/133611151这里的渗透线上下料属于整个渗透线流程里的最前端和最后端&#xff0c;分别负责待处理…

《Linux系统与网络管理》复习题库---简答题

1、简述这些分区的名字以及各自的作用。 答&#xff1a; /boot 存放内核镜像的地方&#xff0c;这个文件夹独立分区的意义在于降低不能开机的风险。 /根目录&#xff0c;一般采用 ext3 文件系统&#xff0c;分区的容量一定要大于安装软件包的容量。 /usr 多数软件的默认安装的地…

Anaconda3 2021.11安装

1. 镜像下载&#xff1a;Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 2. 安装在D盘&#xff1a; 3. 配置环境变量&#xff1a; 在这里&#xff0c;第一个教程A在系统变量里配置了五个&#xff0c;但我没有 所以又搜了教程B&#xf…

扎根底层技术,推动机器人换代式升级

热赛道和冷市场的矛盾之下&#xff0c;机器人需要一次换代式升级。 冷中有热的资本市场 在宏观经济下行的影响下&#xff0c;我国服务机器人产量从2022年开始出现明显放缓&#xff0c;2021年12月至2022年12月&#xff0c;我国服务机器人产量都处于同比下滑的状态&#xff0c;…

LeetCode每日一题.05(N皇后)

按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。 每一种…

以元旦为题的诗词(三)

愿新的一年给我们带来无尽的好运和幸福愿我们的梦想在新的起点绽放! 让我们在未来的日子里书写新的篇章! 接着分享几首以元旦为题的几首诗&#xff0c;喜欢的朋友可以自取&#xff0c;想要更多免费的诗词&#xff0c;请自行百度或小程序搜索&#xff1a;美诗计 元旦 元旦佳节…

剑指“CPU飙高”问题

一、什么是cpu飙高&#xff1f; 一般指程序运行时cpu占用率过高   linux系统中&#xff0c;我们使用top命令&#xff0c;会看到正在运行进程的cpu使用率等&#xff0c;同时在最上面也会看到总的cpu使用率&#xff0c;当总的cpu使用率过高&#xff0c;如果有运维监控平台&…

【Linux】理解文件系统

需要云服务器等云产品来学习Linux的同学可以移步/–>腾讯云<–/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;优惠多多。&#xff08;联系我有折扣哦&#xff09; 文章目录 1. 了解磁盘1.1 磁盘的物理结构1.2 磁盘的逻辑结构1.3 磁盘的存储结构 2. 文件系统2.…

2023年12月编程语言排行榜

TIOBE Index for December 2023 December Headline: C# on its way to become programming language of the year 2023 2023年12月的TIOBE指数&#xff1a;12月头条:c#将成为2023年最佳编程语言 Yes, I know, we have been here before. At the end of 2022, it looked like …

全局异常和自定义异常处理

全局异常GlobalException.java&#xff0c;basePackages&#xff1a;controller层所在的包全路径 import com.guet.score_management_system.common.domian.AjaxResult; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bi…

电脑怎么设置代理IP上网?如何隐藏自己电脑的真实IP?

在现代互联网中&#xff0c;代理IP已成为许多用户保护隐私和上网安全的重要手段。通过设置代理IP&#xff0c;用户可以隐藏自己的真实IP地址&#xff0c;提高上网的安全性&#xff0c;同时保护个人信息不被泄露。本文将详细介绍如何设置代理IP上网以及如何隐藏电脑的真实IP地址…

Vue Tinymce富文本组件添加自定义字体项

实现效果如下&#xff1a; Tinymce 组件进行字体设置 设置完后&#xff0c;就可以使用自定义的字体了。

Spring Boot整合 EasyExcel 实现复杂 Excel 表格的导入与导出功能

文章目录 1. 简介2. 引入依赖3. 导入功能实现3.1 创建实体类3.2 编写导入 Controller3.3 编写导入页面 4. 导出功能实现4.1 编写导出 Controller4.2 编写导出页面 5. 启动应用 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &…

你好2024!

大家好&#xff0c;我是小悟 2024年1月1日&#xff0c;新年的第一天&#xff0c;阳光明媚&#xff0c;空气中弥漫着希望和新的开始的气息。在这个特别的日子里&#xff0c;大家纷纷走出家门&#xff0c;迎接新年的到来。 街道上&#xff0c;熙熙攘攘的人群中&#xff0c;有孩…

【动态管理日志】Spring Boot 实现 热插拔 AOP,非常实用!

现在有这么一个需求&#xff1a;就是我们日志的开与关是交给使用人员来控制的&#xff0c;而不是由我们开发人员固定写死的。大家都知道可以用aop来实现日志管理&#xff0c;但是如何动态的来实现日志管理呢&#xff1f;aop源码中的实现逻辑中有这么一个步骤&#xff0c;就是会…

将学习自动化测试时的医药管理信息系统项目用idea运行

将学习自动化测试时的医药管理信息系统项目用idea运行 背景 学习自动化测试的时候老师的运行方式是把医药管理信息系统项目打包成war包后再放到tomcat的webapp中去运行&#xff0c;于是我想着用idea运行会方便点&#xff0c;现在记录下步骤方便以后查找最开始没有查阅资料&am…

蓝牙物联网灯控设计方案

蓝牙技术是当前应用最广泛的无线通信技术之一&#xff0c;工作在全球通用的 2.4GHZ 的ISM 频段。蓝牙的工作距离约为 100 米&#xff0c;具有一定的穿透性&#xff0c;没有方向限制。具有低成本、抗干扰能力强、传输质量高、低功耗等特点。蓝牙技术组网比较简单&#xff0c;无需…