QML使用QCustomPlot笔记
这里在QML中使用QCustomPlot是定义一个继承自QQuickPaintedItem的类,它包含一个QCustomPlot对象,在paint函数中将这个对象转化为pixmap绘制到布局中显示。
在QML中使用QT的Widget控件也可以借鉴这个思路实现
顺便记录一下QCustomPlot的简单设置与使用。
QCustomPlot可以直接到官网下载源码。
main.cpp中添加代码,将C++类注册为QML组件
#include "plot/liquidheightplot.h"
...int main(int argc, char *argv[])
{
...qmlRegisterType<LiquidHeightPlot>("LiquidHeightPlot", 1, 0, "LiquidHeightPlot");
...
}
类定义liquidheightplot.h
#ifndef LIQUIDHEIGHTPLOT_H
#define LIQUIDHEIGHTPLOT_H#include "qcustomplot/qcustomplot.h"
#include <QQuickItem>
#include <QQuickPaintedItem>
#include <QVector>
#include <QJsonObject>class LiquidHeightPlot : public QQuickPaintedItem
{Q_OBJECT
public:explicit LiquidHeightPlot(QQuickItem *parent = nullptr);~LiquidHeightPlot();//更新实时数据Q_INVOKABLE void updateRealData(double value);//设置历史数据Q_INVOKABLE void setHistoryData(QJsonObject data);//清除数据Q_INVOKABLE void clearData();signals:void sigIllegalData();private:virtual void paint(QPainter *painter);private:QCustomPlot *m_customPlot;double m_maxY;QVector<double> m_x1;QVector<double> m_y1;
};#endif // LIQUIDHEIGHTPLOT_H
类实现liquidheightplot.cpp
#include "liquidheightplot.h"
#include <QDateTime>
#include <QStringList>LiquidHeightPlot::LiquidHeightPlot(QQuickItem *parent): QQuickPaintedItem(parent), m_customPlot(nullptr)
{m_customPlot = new QCustomPlot();m_customPlot->rescaleAxes(true);//设置轴 ============================QFont font;font.setPixelSize(16);m_customPlot->xAxis->setLabelFont(font);m_customPlot->yAxis->setLabelFont(font);m_customPlot->xAxis->setLabel(tr("时间"));m_customPlot->yAxis->setLabel(tr("液位高度(cm)"));m_customPlot->xAxis->setLabelColor(QColor(Qt::gray));//轴标体色m_customPlot->yAxis->setLabelColor(QColor(Qt::gray));m_customPlot->xAxis->setBasePen(QPen(QColor(Qt::gray), 1));//轴色m_customPlot->yAxis->setBasePen(QPen(QColor(Qt::gray), 1));m_customPlot->xAxis->setTickPen(QPen(QColor(Qt::gray), 1));//轴主标色m_customPlot->yAxis->setTickPen(QPen(QColor(Qt::gray), 1));m_customPlot->xAxis->setSubTickPen(QPen(QColor(Qt::gray), 1));//轴次标色m_customPlot->yAxis->setSubTickPen(QPen(QColor(Qt::gray), 1));font.setPixelSize(14);m_customPlot->xAxis->setTickLabelFont(font);m_customPlot->yAxis->setTickLabelFont(font);m_customPlot->xAxis->setTickLabelColor(QColor(Qt::gray));//轴标文本色m_customPlot->yAxis->setTickLabelColor(QColor(Qt::gray));m_customPlot->setBackground(QBrush(QColor(Qt::white)));m_customPlot->setGeometry(0, 0, width()*1.6, height()*1.6);m_customPlot->setMultiSelectModifier(Qt::KeyboardModifier::ControlModifier);//设置边距QCPMarginGroup *marginGroup = new QCPMarginGroup(m_customPlot);m_customPlot->plotLayout()->setMargins(QMargins(0, 0, 0, 0));m_customPlot->axisRect()->setMarginGroup(QCP::msLeft | QCP::msRight | QCP::msTop | QCP::msBottom, marginGroup);//设置时间轴QSharedPointer<QCPAxisTickerDateTime> dateTicker(new QCPAxisTickerDateTime);dateTicker->setDateTimeFormat("yyyyMMdd\nhh:mm");m_customPlot->xAxis->setTicker(dateTicker);QString sCurrent = QDateTime::currentDateTime().toString("yyyyMMdd hh:00:00");QDateTime current = QDateTime::fromString(sCurrent, "yyyyMMdd hh:mm:ss");m_customPlot->xAxis->setRange(current.toTime_t(), current.toTime_t() + 1800);//默认显示时间轴当前半小时//纵轴QSharedPointer<QCPAxisTicker> ticker(new QCPAxisTicker);m_customPlot->yAxis->setTicker(ticker);m_customPlot->yAxis->setRange(0, 200);//添加数据曲线图形m_customPlot->addGraph();m_customPlot->graph(0)->setPen(QPen(Qt::blue));//显示图例QCPLegend * legend = m_customPlot->legend;m_customPlot->legend->setVisible(true);legend->setFont(font);legend->setBrush(QColor(Qt::gray));legend->setTextColor(QColor(Qt::white));m_customPlot->graph(0)->setName("液位曲线");//设置clearData();
}LiquidHeightPlot::~LiquidHeightPlot()
{m_customPlot->deleteLater();m_customPlot = nullptr;
}void LiquidHeightPlot::paint(QPainter *painter)
{m_customPlot->setGeometry(0,0,this->width()*1.6,this->height()*1.6);painter->drawPixmap(0,0,this->width(),this->height(), m_customPlot->toPixmap());
}//更新实时数据
void LiquidHeightPlot::updateRealData(double value)
{QDateTime current = QDateTime::currentDateTime();if(m_x1.size() == 0) {//第一帧实时数据m_customPlot->xAxis->setRange(current.toTime_t(), current.toTime_t() + 1800);}if(m_x1.size() > 0 && m_x1.last() == current.toTime_t()) return;//同一时间的数据while (m_x1.size() >= 30) {//半小时,30个数据m_x1.takeFirst();m_y1.takeFirst();}m_x1.push_back(current.toTime_t());m_y1.push_back(value);if(m_maxY < value) {//更新最大值m_maxY = value;m_maxY = (m_maxY / 10 + 1) * 10;m_customPlot->yAxis->setRange(0, m_maxY);}if(m_x1.size() == 30) m_customPlot->xAxis->setRange(m_x1.first(), m_x1.last());//更新轴m_customPlot->graph(0)->setData(m_x1, m_y1);m_customPlot->replot();//刷新曲线update();//刷新显示
}//设置历史数据
//"data": {
// "maxLiquidLevelHeight": "68,88",
// "minLiquidLevelHeight": "68,88",
// "time": "2023-01-02 22:59:59,2023-01-02 23:59:59",
// }
void LiquidHeightPlot::setHistoryData(QJsonObject data)
{QString maxLiquidLevelHeight = data["maxLiquidLevelHeight"].toString();QString times = data["time"].toString();maxLiquidLevelHeight.remove('\n');times.remove('\n');QStringList heightList = maxLiquidLevelHeight.split(",", QString::SkipEmptyParts);QStringList timeList = times.split(",", QString::SkipEmptyParts);if (heightList.count() != timeList.count()) {qDebug() << "LiquidHeightPlot::setHistoryData error heightList.count() != timeList.count() !";return;}for (int i = 0; i < heightList.count(); i++) {QDateTime time = QDateTime::fromString(timeList[i], "yyyy-MM-dd HH:mm:ss");qDebug() << "LiquidHeightPlot::setHistoryData time isValid " << time.isValid() << time;if(!time.isValid()) {//存在非法数据emit sigIllegalData();return;}uint value = heightList[i].toInt();m_x1.append(time.toTime_t());m_y1.append(value);if(m_maxY < value) {//更新最大值m_maxY = value;m_maxY = (m_maxY / 10 + 1) * 10;m_customPlot->yAxis->setRange(0, m_maxY);}}m_customPlot->xAxis->setRange(m_x1.first(), m_x1.last());m_customPlot->graph(0)->setData(m_x1, m_y1);m_customPlot->replot();//刷新曲线update();//刷新显示qDebug() << "LiquidHeightPlot::setHistoryData m_x1" << m_x1 << ",\n m_y1" << m_y1;
}//清除数据
void LiquidHeightPlot::clearData()
{qDebug() << "LiquidHeightPlot::clearData ---------------------------------";m_maxY = 200;m_x1.clear();m_y1.clear();m_customPlot->graph(0)->setData(m_x1, m_y1);m_customPlot->replot();//刷新曲线update();//刷新显示
}
QML的使用
import LiquidHeightPlot 1.0Item {id: root
...LiquidHeightPlot {id: liquidHeightPlotanchors.fill: parentonSigIllegalData: {popuTip.text = qsTr("数据异常 !");popuTip.visible = true;}}
...
}
相关文章:
QML使用QCustomPlot笔记
这里在QML中使用QCustomPlot是定义一个继承自QQuickPaintedItem的类,它包含一个QCustomPlot对象,在paint函数中将这个对象转化为pixmap绘制到布局中显示。 在QML中使用QT的Widget控件也可以借鉴这个思路实现 顺便记录一下QCustomPlot的简单设置与使用。…...
【REST2SQL】06 GO 跨包接口重构代码
【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 对所有关系数据的操作都只有CRUD,采用Go 的接口interface{}重构代码…...
《NLP入门到精通》栏目导读
一、说明 栏目《NLP入门到精通》本着从简到难得台阶式学习过度。将自然语言处理得知识贯穿过来。本栏目得前导栏目是《深度学习》、《pytorch实践》,因此,读者需要一定得深度学习基础,才能过度到此栏目内容。 二、博客建设理念 本博客基地&am…...
C++学习笔记——类继承
目录 一、一个简单的基类 1.1封装性 1.2继承性 1.3虚函数 1.4多态性 二、基类 2.1一个简单的C基类的示例 2.2 Animal是一个基类。 三、继承 3.1概念 3.2is-a关系 3.3多态公有继承 3.4静态联编和动态联编 3.5访问控制 3.6ABC理念 一、一个简单的基类 C中的基类是一…...
ARCGIS PRO SDK 使用条件管理 Pro UI
ARCGIS PRO UI简单介绍以下: 第一步:在Config.daml中在</AddInfo>标签下加上条件<conditions>标签(必须添加的) <conditions><!-- 定义条件 ,此处定义了两个--Tab 另一个为 group><insert…...
Halcon经典的边缘检测算子Sobel/Laplace/Canny
Halcon经典的边缘检测算子 文章目录 Halcon经典的边缘检测算子1. Sobel算子2. Laplace 算子3. Canny 算子4. 总结 关于边缘检测,有许多经典的算子,各大图形处理库都有各自的边缘检测算子,这里简要介绍几种。 1. Sobel算子 Sobel算子结合了高…...
用单片机设计PLC电路图
自记: 见另一篇文章,MOS驱动差了一个充电电容,栅极电容充电会有问题; 光耦用的直插,但板子用的贴片,此文档仅供参考 基本列出了PCB板情况,基础元器件,部分连接,原理等…...
【设计模式-6】建造者模式的实现与框架中的应用
建造者模式又被成为生成器模式,是一种使用频率比较低,相对复杂的创建型模式,在很多源码框架中可以看到建造者的使用场景,稍后我们会在本文末尾展示几个框架的使用案例。 建造者模式所构造的对象通常是比较复杂而且庞大的&#x…...
PositiveSSL和Sectigo的多域名证书
首先,我们要知道PositiveSSL是Sectigo旗下的子品牌,提供多种类型的SSL数字证书,包括DV基础型的多域名SSL证书。Sectigo的SSL证书产品同样比较丰富,不仅有DV基础型多域名SSL证书,还有OV企业型以及EV增强型的多域名SSL证…...
Docker:docker exec命令简介
介绍 docker exec [OPTIONS] 容器名称 COMMAND [ARG...] OPTIONS说明: -d,以后台方式执行命令; -e,设置环境变量 -i,交互模式 -t,设置TTY -u,用户名或UID,例如myuser:myu…...
【大数据进阶第三阶段之Hive学习笔记】Hive的数据类型与数据操作
目录 1、Hive数据类型 1.1、基本数据类型 1.2、集合数据类型 1.3、类型转化 2、DDL数据定义 2.1、创建数据库 2.2、查询数据库 2.3删除数据库 2.4、创建表 2.4.1、内部表 2.4.2、外部表 2.4.3管理表与外部表的互相转换 2.5、分区表(partitionÿ…...
GPT2:Language Models are Unsupervised Multitask Learners
目录 一、背景与动机 二、卖点与创新 三、几个问题 四、具体是如何做的 1、更多、优质的数据,更大的模型 2、大数据量,大模型使得zero-shot成为可能 3、使用prompt做下游任务 五、一些资料 一、背景与动机 基于 Transformer 解码器的 GPT-1 证明…...
微创新与稳定性的权衡
之前做过一个项目,业务最高峰CPU使用率也才50%,是一个IO密集型的应用。里面涉及一些业务编排,所以为了提高CPU使用率,我有两个方案:一个是简单的梳理将任务可并行的采用并行流、额外线程池等方式做并行;另外…...
对回调函数的各种讲解说明
有没有跟我师弟一样的童靴~,学习和使用ROS节点时,对其中的callback函数一直摸不着头脑的,以下这么多回调函数的讲解,挨个看,你总会懂的O.o 回调函数怎么调用,如何定义回调函数: 回调函数怎么调用,如何定义…...
Java多线程:创建多线程的三种方式
在Java中,有三种方式创建多线程,继承类Thread,继承接口Runnable,继承接口Callable。其中Thread和Runnable需要重写方法run,方法run没有返回值;Callable需要重写方法call,方法call可以返回值。 …...
Unity中打印信息的两种方式
不继承MonoBehaviour的普通C#类中打印信息: 使用Debug类的方法: Unity提供了Debug类,其中包含了一些用于打印信息的静态方法。以下是常用的几种方法: Debug.Log(message):打印普通信息。Debug.LogWarning(message)&a…...
给定n个字符串s[1...n], 求有多少个数对(i, j), 满足i < j 且 s[i] + s[j] == s[j] + s[i]?
题目 思路: 对于字符串a,b, (a.size() < b.size()), 考虑对字符串b满足什么条件: 由1、3可知a是b的前后缀,由2知b有一个周期是3,即a.size(),所以b是用多个a拼接而成的,有因为a是b的前后缀&…...
Linux磁盘空间与文件大小查看命令详解
1. 查看磁盘空间大小 在Linux系统中,有多个命令可以用来查看磁盘空间的使用情况。最常用的命令是df(disk free)。 df -hdf命令的 -h 选项以人类可读的方式显示磁盘空间,该命令将显示文件系统的使用情况、剩余空间等信息。 2. 查看…...
网络通信过程的一些基础问题
客户端A在和服务器进行TCP/IP通信时,发送和接收数据使用的是同一个端口吗? 这个问题可以这样来思考:在客户端A与服务器B建立连接时,A需要指定一个端口a向服务器发送数据。当服务器接收到A的报文时,从报文头部解析出A的…...
STL——stack容器和queue容器详解
目录 💡stack 💡基本概念 常用接口 💡queue 💡基本概念 💡常用接口 💡stack 💡基本概念 栈(stack):一种特殊的线性表,其只允许在固定的一端…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
