当前位置: 首页 > news >正文

QPaint绘制自定义坐标轴组件00

最终效果

1.创建一个ui页面,修改背景颜色

鼠标右键->改变样式表->添加颜色->background-color->选择合适的颜色->ok->Apply->ok

重新运行就可以看到widget的背景颜色已经改好

2.创建一个自定义的widget窗口小部件类,class MyChart : public QWidget

mychart.h

#ifndef MYCHART_H
#define MYCHART_H#include <QWidget>
#include <QPainter>
#include <QString>struct DataNode
{int value;QString key;
};// MyChart继承自QWidget类,是一个窗口小部件。
class MyChart : public QWidget
{Q_OBJECT
public:// `explicit` 是 C++ 中的一个关键字,用于修饰类的构造函数,表示该构造函数只能用于显式地创建对象,不能被隐式地调用。// 只能通过MyChart painter = MyChart(parent)的方式显式地创建一个 `MyChart` 对象:// `parent` 参数的默认值为 `nullptr`,这表示如果没有提供父部件的指针,那么 `MyChart` 就没有父部件,即它是一个独立的窗口部件。explicit MyChart(QWidget *parent = nullptr);void updateValue(const DataNode &node);protected:// `paintEvent(QPaintEvent *event)` 是一个事件处理函数,// 在 Qt 框架中,当需要重绘窗口部件时就会自动触发 `paintEvent(QPaintEvent *event)` 函数,// 以便开发者可以实现窗口部件的绘制逻辑,从而更新窗口的显示内容。// 在窗口需要进行重绘时,Qt 框架会自动调用 `MyChart` 对象的 `paintEvent(QPaintEvent *event)` 函数,从而实现图表的绘制更新。// 由于 `paintEvent` 函数是在需要重绘窗口部件时自动调用的,因此我们不需要手动调用它。// 当然,如果需要手动更新窗口部件的显示内容,// 也可以使用 `QWidget` 类中提供的 `update()` 函数或 `repaint()` 函数来触发 `paintEvent` 函数的调用,// 从而实现窗口的重绘。但通常情况下,Qt 框架会自动处理窗口部件的刷新和重绘。// `paintEvent` 函数是在 `QWidget` 类中定义的虚函数,// 它被设计为在窗口部件需要重新绘制时自动调用,以便让程序员有机会对窗口的内容进行绘制修改。// 在 `QWidget` 子类中,如果需要修改默认的绘制行为,则可以重写 `paintEvent` 函数来实现。void paintEvent(QPaintEvent *event);private:int yMaxValue = 10;int maxNodeNum = 110;QList<DataNode> listDataNode;
};#endif // MYCHART_H

 mychart.cpp

#include "mychart.h"MyChart::MyChart(QWidget *parent) : QWidget(parent)
{}// 数据刷新
void MyChart::updateValue(const DataNode &node)
{// 如果当前列表中的数据节点数量已经达到了最大值 `maxNodeNum`,// 先删除队列头部的元素,即最早加入的元素(使用 `removeFirst()` 函数)。if(listDataNode.size() >= maxNodeNum) {listDataNode.removeFirst();}// 然后,将数据节点 `node` 添加到当前列表的末尾,使用 `append()` 函数实现。listDataNode.append(node);// 最后,将整个图表更新,调用 `update()` 函数。// `update()` 函数是用来触发 `paintEvent()` 函数的信号的。// 当窗口或控件需要更新或重绘自己时,它们会同时发射一个 `update()` 信号。// 这个信号会被 Qt 的事件循环机制捕获,最终调用 `paintEvent()` 函数进行绘图。// 因此,如果不调用 `update()` 函数,`paintEvent()` 函数就不会被调用,也就不会更新图表的显示内容。update();
}// 图标绘制
// `paintEvent` 函数中的调用实际上是在继承关系中向上查找到的 `QWidget::paintEvent()` 函数的实现,
// 它在需要绘制更新时被自动触发。
// 在默认情况下,这个函数为空实现,因此需要我们手动重写它并自己实现绘图功能。
void MyChart::paintEvent(QPaintEvent *event)
{(void)event;// `QPainter` 是 Qt 中的一个绘图工具类,它封装了各种绘制函数和处理设备上下文的能力。// 通过使用 `QPainter` 类可以在窗口、部件和其它设备上上进行绘图操作。// 通过调用 `painter` 的各种绘制函数可以在空白的窗口部件上一步步画出你需要的复杂图形,包括直线、圆弧、多边形、文本等等。// `this` 关键字是指向当前对象的指针,即指向调用成员函数的对象的指针。// `this` 关键字可以用来访问对象的成员变量和成员函数,区分局部变量和成员变量。// `this` 指的是当前 `MyChart` 类型的对象,也就是指示当前需要绘制图表的部件对象。// 在这个函数中,我们通过将对象指针传给 `QPainter` 构造函数,来创建一个绘制器,使用它进行绘图操作。// 需要注意的是,`this` 关键字指向的是对象的指针,而不是类本身。// 所以说,`this` 不是用来区分类和对象的关键字,而是用来访问对象内部成员的工具。QPainter painter(this);// 启用抗锯齿功能,即让绘制的线条、边缘等对锯齿进行平滑处理,让图像更加平滑和自然。painter.setRenderHint(QPainter::Antialiasing);// `QPen` 是 Qt 中的一个画笔类,用于控制绘图时线条的样式、颜色和粗细等参数,通常与 `QPainter` 类一起使用。// 在默认情况下,`QPen` 对象的颜色为黑色,线宽为0,样式为实线。// 可以通过 `setBrush()`、`setColor()`、`setWidth()`、`setStyle()` 等函数来设置画笔的各个属性。QPen pen;pen.setWidth(2);pen.setColor(QColor(100, 200, 100));// setPen(pen)将创建的 `QPen` 画笔对象传入painter,就可以使用该笔刷来绘制线条、形状、文本等各种图形元素了。painter.setPen(pen);//坐标轴// 高度int yLength = this->height() * 0.9;// 长度int xLength = this->width();// `QPoint` 类是 Qt 中的一个点类,用于表示二维平面坐标系中的一个点,其具体坐标值由 `x()` 和 `y()` 成员函数获取。// `zero` 是一个 `QPoint` 类型的点,由横坐标`this->width() * 0.03`纵坐标`this->height() * 0.95` 两个数值组成,// 它代表了坐标系中的原点或者起始点,用来确定坐标轴的位置。QPoint zero(this->width() * 0.03, this->height() * 0.95);// 以下两行代码通常表示绘制一个基础的坐标系,绘制坐标系通常是绘制图表的第一步,是各种图表展示中的基础步骤之一。// 从 `zero` 点开始,向上绘制一条长度为 `yLength` 的水平线段表示y轴,并向右绘制一条长度为 `xLength` 的垂直线段表示x轴。// 这里使用了 `QPoint` 类型的构造函数创建起始点和结束点的对象。// y轴,原点zero,终点QPoint(zero.x() + xLength, zero.y())painter.drawLine(zero, QPoint(zero.x(), zero.y() - yLength));// x轴,原点zero,终点QPoint(zero.x() + xLength, zero.y())painter.drawLine(zero, QPoint(zero.x() + xLength, zero.y()));// 刻度间隔数int durationX = 100;int durationY = 10;// 每个刻度之间间隔的长度int xPeriod = xLength / durationX - 1;int yPeriod = yLength / durationY - 1;// 绘制坐标轴上的刻度和数字,用以标示坐标轴上每个刻度对应的数值// 遍历 y 轴的每个刻度位置,从起点 `zero` 开始向上连续绘制 `durationY` 个横向线段用于表示刻度。for (int i = 0; i <= durationY; ++i) {// 绘制表示y轴刻度的水平线段painter.drawLine(QPoint(zero.x() - 1, zero.y() - i * yPeriod), QPoint(zero.x() + 5, zero.y() - i * yPeriod));QString value = QString::number(i * 2);// 绘制刻度数值painter.drawText(QPoint(zero.x() - 25, zero.y() - i * yPeriod + 5), value);}for (int i = 0; i < durationX; ++i) {// 绘制表示x轴刻度的垂直线段painter.drawLine(QPoint(zero.x() + i * xPeriod, zero.y() + 3), QPoint(zero.x() + i * xPeriod, zero.y() - 5));}// 更新数据QList<QPoint> pointList;for(int i = 0; i < listDataNode.size(); i++) {DataNode node = listDataNode.at(i);QString key = node.key;int value = node.value;// 当前数据在x轴位置对应的刻度值int xOffset = zero.x() + i * xPeriod;// 当前数据在y轴位置对应的刻度值int yOffset = value * yLength / yMaxValue;// 像数据列表中添加数据转换后对应的坐标点pointList << QPoint(xOffset, zero.y() - yOffset);// 使用 `QTransform` 类对绘制坐标文本的位置和方向进行变换QTransform transform;// `translate()` 函数将文本的绘制起点平移 (`xOffset + 5`, `zero.y() - 7`) 的位置,// 即向右偏移5个像素,向上偏移7个像素,这是调试后比较合适的显示位置transform.translate(xOffset + 5, zero.y() - 7);// `rotate(-45)` 函数将文本沿顺时针方向旋转 45 度。transform.rotate(-45);// `setTransform()` 函数将 transform 对象设置为画笔对象 painter 的当前变换矩阵。painter.setTransform(transform);// `drawText()` 函数在变换后的位置绘制文本。painter.drawText(0, 5, key);// `resetTransform()` 函数将画笔对象的变换矩阵重置为原始状态。// 这个步骤很重要,如果不重置的话,下次绘制的文本会沿之前的变换矩阵进行绘制。painter.resetTransform();}// 折线线条宽度pen.setWidth(3);// 折现线条颜色pen.setColor(Qt::red);painter.setPen(pen);// 遍历并连接个数据节点,绘制折线for(int i = 0; i < pointList.size(); i++) {if((i+1) < pointList.size()) {// 连接个数据点,绘制折线painter.drawLine(pointList.at(i), pointList.at(i+1));}}
}

3.添加一个用于绘制自定义控件的控件,一般是Qwidget,修改QWidget的类属性,提升为自定义的类

提升类完成后qt designer显示当前组件已经是MyChart类

 重新编译运行后,原来的QWidget子窗口页面变成了自定义的Mychart页面

编写应用代码,应用自己编写的MyChart类实现数据刷新

charttest.h

#ifndef CHARTTEST_H
#define CHARTTEST_H#include <QWidget>
#include <QTimer>
#include <QTime>
#include "mychart.h"QT_BEGIN_NAMESPACE
namespace Ui { class ChartTest; }
QT_END_NAMESPACEclass ChartTest : public QWidget
{Q_OBJECTpublic:ChartTest(QWidget *parent = nullptr);~ChartTest();void initState();private:Ui::ChartTest *ui;int index = 0;QTimer timer;   //定时器
};
#endif // CHARTTEST_H

charttest.cpp 

#include "charttest.h"
#include "ui_charttest.h"ChartTest::ChartTest(QWidget *parent): QWidget(parent), ui(new Ui::ChartTest)
{ui->setupUi(this);initState();
}ChartTest::~ChartTest()
{timer.stop();delete ui;
}void ChartTest::initState()
{this->resize(1000, 400);connect(&timer, &QTimer::timeout, [=](){// 模拟数据static int y = 1;if (y++ >= 9) {y = 1;}static int value = 0;DataNode node = {y, "ABC" + QString::number(value++)};// 刷新数据ui->widget->updateValue(node);});timer.start(50);
}

main.cpp 

#include "charttest.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);ChartTest w;w.show();return a.exec();
}

ChartTest.pro 

QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \charttest.cpp \mychart.cppHEADERS += \charttest.h \mychart.hFORMS += \charttest.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

编写晚代码后运行效果

 

相关文章:

QPaint绘制自定义坐标轴组件00

最终效果 1.创建一个ui页面&#xff0c;修改背景颜色 鼠标右键->改变样式表->添加颜色->background-color->选择合适的颜色->ok->Apply->ok 重新运行就可以看到widget的背景颜色已经改好 2.创建一个自定义的widget窗口小部件类&#xff0c;class MyChart…...

MATLAB|基于改进二进制粒子群算法的含需求响应机组组合问题研究(含文献和源码)

目录 主要内容 模型研究 1.改进二进制粒子群算法&#xff08;BPSO&#xff09; 2.模型分析 结果一览 下载链接 主要内容 该程序复现《A Modified Binary PSO to solve the Thermal Unit Commitment Problem》&#xff0c;主要做的是一个考虑需求响应的机组组合…...

JDBC核心技术

第1章 JDBC概述 第2章 获取数据库连接 第3章 使用PreparedStatement实现CRUD操作 第4章 操作BLOB类型字段 第5章 批量插入 第6章 数据库事务 第7章 DAO及相关实现类 第8章 数据库连接池 第9章 Apache-DBUtils实现CRUD操作图像 小部件...

【天幕系列 02】开源力量:揭示开源软件如何成为技术演进与社会发展的引擎

文章目录 导言01 开源软件如何推动技术创新1.1 开放的创新模式1.2 快速迭代和反馈循环1.3 共享知识和资源1.4 生态系统的建设和扩展1.5 开放标准和互操作性 02 开源软件的商业模式2.1 支持和服务模式2.2 基于订阅的模式2.3 专有附加组件模式2.4 开源软件作为平台模式2.5 双重许…...

“挖矿”系列:细说Python、conda 和 pip 之间的关系

继续挖矿&#xff0c;挖“金矿”&#xff01; 1. Python、conda 和 pip&#xff08;挖“金矿”工具&#xff09; Python、conda 和 pip 是在现代数据科学和软件开发中常用的工具&#xff0c;它们各自有不同的作用&#xff0c;但相互之间存在密切的关系&#xff1a; Python&…...

【自然语言处理】实验3,文本情感分析

清华大学驭风计划课程链接 学堂在线 - 精品在线课程学习平台 (xuetangx.com) 代码和报告均为本人自己实现&#xff08;实验满分&#xff09;&#xff0c;只展示主要任务实验结果&#xff0c;如果需要详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢…...

2.12日学习打卡----初学RocketMQ(三)

2.12日学习打卡 目录&#xff1a; 2.12日学习打卡一. RocketMQ高级特性&#xff08;续&#xff09;消息重试延迟消息消息查询 二.RocketMQ应用实战生产端发送同步消息发送异步消息单向发送消息顺序发送消息消费顺序消息全局顺序消息延迟消息事务消息消息查询 一. RocketMQ高级特…...

<网络安全>《35 网络攻防专业课<第一课 - 网络攻防准备>》

1 主要内容 认识黑客 认识端口 常见术语与命令 网络攻击流程 VMWare虚拟环境靶机搭建 2 认识黑客 2.1 白帽、灰帽和黑帽黑客 白帽黑客是指有能力破坏电脑安全但不具恶意目的黑客。 灰帽黑客是指对于伦理和法律态度不明的黑客。 黑帽黑客经常用于区别于一般&#xff08;正面…...

【实战】一、Jest 前端自动化测试框架基础入门(一) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(一)

文章目录 一、前端要学的测试课1.前端要学的测试2.前端工程化的一部分3.前端自动化测试的例子4.前端为什么需要自动化测试&#xff1f;5.课程涵盖内容6.前置技能7.学习收获 二、Jest 前端自动化测试框架基础入门1. 自动化测试背景及原理前端自动化测试产生的背景及原理 2.前端自…...

蓝桥杯Java组备赛(二)

题目1 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int max Integer.MIN_VALUE;int min Integer.MAX_VALUE;double sum 0;for(int i0;i<n;i) {int x sc.nextInt()…...

人力资源智能化管理项目(day10:首页开发以及上线部署)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/humanResourceIntelligentManagementProject 首页-基本结构和数字滚动 安装插件 npm i vue-count-to <template><div class"dashboard"><div class"container"><!-- 左侧内…...

Conda管理Python不同版本教程

Conda管理Python不同版本教程 目录 0.前提 1.conda常用命令 2.conda设置国内源&#xff08;以添加清华源为例&#xff0c;阿里云源同样&#xff09; 3.conda管理python库 4.其它 不太推荐 pyenv管理Python不同版本教程&#xff08;本人另一篇博客&#xff0c;姊妹篇&…...

free pascal:fpwebview 组件通过 JSBridge 调用本机TTS

从 https://github.com/PierceNg/fpwebview 下载 fpwebview-master.zip 简单易用。 先请看 \fpwebview-master\README.md cd \lazarus\projects\fpwebview-master\demo\js_bidir 学习 js_bidir.lpr &#xff0c;编写 js_bind_speak.lpr 如下&#xff0c;通过 JSBridge 调用本…...

数据结构——单链表专题

目录 1. 链表的概念及结构2. 实现单链表初始化尾插头插尾删头删查找在指定位置之前插入数据在指定位置之后插入数据删除指定位之前的节点删除指定位置之后pos节点销毁链表 3. 完整代码test.cSList.h 4. 链表的分类 1. 链表的概念及结构 在顺序表中存在一定的问题&#xff1a; …...

Linux:开源世界的王者

在科技世界中&#xff0c;Linux犹如一位低调的王者&#xff0c;统治着开源世界的半壁江山。对于许多技术爱好者、系统管理员和开发者来说&#xff0c;Linux不仅仅是一个操作系统&#xff0c;更是一种信仰、一种哲学。 一、开源的魅力 Linux的最大魅力在于其开源性质。与封闭的…...

⭐北邮复试刷题103. 二叉树的锯齿形层序遍历 (力扣每日一题)

103. 二叉树的锯齿形层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此类推&#xff0c;层与层之间交替进行&#xff09;。 示例 1&#xff1a;输入&#xff1a…...

文件上传漏洞--Upload-labs--Pass07--点绕过

一、什么是点绕过 在Windows系统中&#xff0c;Windows特性会将文件后缀名后多余的点自动删除&#xff0c;在网页源码中&#xff0c;通常使用 deldot()函数 对点进行去除&#xff0c;若发现网页源代码中没有 deldot() 函数&#xff0c;则可能存在 点绕过漏洞。通过点绕过漏洞&…...

MySQL高级特性篇(1)-JSON数据类型的应用

MySQL是一种常用的关系型数据库管理系统&#xff0c;它提供了多种数据类型&#xff0c;其中包括JSON数据类型。JSON&#xff08;JavaScript Object Notation&#xff09;是一种常用的数据交换格式&#xff0c;它以键值对的形式组织数据&#xff0c;并支持嵌套和数组结构。MySQL…...

如何用Qt实现一个无标题栏、半透明、置顶(悬浮)的窗口

在Qt框架中&#xff0c;要实现一个无标题栏、半透明、置顶&#xff08;悬浮&#xff09;的窗口&#xff0c;需要一些特定的设置和技巧。废话不多说&#xff0c;下面我将以DrawClient软件为例&#xff0c;介绍一下实现这种效果的四个要点。 要点一&#xff1a;移除标题栏&#…...

ViT: transformer在图像领域的应用

文章目录 1. 概要2. 方法3. 实验3.1 Compare with SOTA3.2 PRE-TRAINING DATA REQUIREMENTS3.3 SCALING STUDY3.4 自监督学习 4. 总结参考 论文&#xff1a; An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 代码&#xff1a;https://github.com…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7

在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤&#xff1a; 第一步&#xff1a; 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为&#xff1a; // 改为 v…...