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

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的类&#xff0c;它包含一个QCustomPlot对象&#xff0c;在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&#xff0c;采用Go 的接口interface{}重构代码…...

《NLP入门到精通》栏目导读

一、说明 栏目《NLP入门到精通》本着从简到难得台阶式学习过度。将自然语言处理得知识贯穿过来。本栏目得前导栏目是《深度学习》、《pytorch实践》&#xff0c;因此&#xff0c;读者需要一定得深度学习基础&#xff0c;才能过度到此栏目内容。 二、博客建设理念 本博客基地&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简单介绍以下&#xff1a; 第一步&#xff1a;在Config.daml中在</AddInfo>标签下加上条件<conditions>标签&#xff08;必须添加的&#xff09; <conditions><!-- 定义条件 &#xff0c;此处定义了两个--Tab 另一个为 group><insert…...

Halcon经典的边缘检测算子Sobel/Laplace/Canny

Halcon经典的边缘检测算子 文章目录 Halcon经典的边缘检测算子1. Sobel算子2. Laplace 算子3. Canny 算子4. 总结 关于边缘检测&#xff0c;有许多经典的算子&#xff0c;各大图形处理库都有各自的边缘检测算子&#xff0c;这里简要介绍几种。 1. Sobel算子 Sobel算子结合了高…...

用单片机设计PLC电路图

自记&#xff1a; 见另一篇文章&#xff0c;MOS驱动差了一个充电电容&#xff0c;栅极电容充电会有问题&#xff1b; 光耦用的直插&#xff0c;但板子用的贴片&#xff0c;此文档仅供参考 基本列出了PCB板情况&#xff0c;基础元器件&#xff0c;部分连接&#xff0c;原理等…...

【设计模式-6】建造者模式的实现与框架中的应用

建造者模式又被成为生成器模式&#xff0c;是一种使用频率比较低&#xff0c;相对复杂的创建型模式&#xff0c;在很多源码框架中可以看到建造者的使用场景&#xff0c;稍后我们会在本文末尾展示几个框架的使用案例。  建造者模式所构造的对象通常是比较复杂而且庞大的&#x…...

PositiveSSL和Sectigo的多域名证书

首先&#xff0c;我们要知道PositiveSSL是Sectigo旗下的子品牌&#xff0c;提供多种类型的SSL数字证书&#xff0c;包括DV基础型的多域名SSL证书。Sectigo的SSL证书产品同样比较丰富&#xff0c;不仅有DV基础型多域名SSL证书&#xff0c;还有OV企业型以及EV增强型的多域名SSL证…...

Docker:docker exec命令简介

介绍 docker exec [OPTIONS] 容器名称 COMMAND [ARG...] OPTIONS说明&#xff1a; -d&#xff0c;以后台方式执行命令&#xff1b; -e&#xff0c;设置环境变量 -i&#xff0c;交互模式 -t&#xff0c;设置TTY -u&#xff0c;用户名或UID&#xff0c;例如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、分区表&#xff08;partition&#xff…...

GPT2:Language Models are Unsupervised Multitask Learners

目录 一、背景与动机 二、卖点与创新 三、几个问题 四、具体是如何做的 1、更多、优质的数据&#xff0c;更大的模型 2、大数据量&#xff0c;大模型使得zero-shot成为可能 3、使用prompt做下游任务 五、一些资料 一、背景与动机 基于 Transformer 解码器的 GPT-1 证明…...

微创新与稳定性的权衡

之前做过一个项目&#xff0c;业务最高峰CPU使用率也才50%&#xff0c;是一个IO密集型的应用。里面涉及一些业务编排&#xff0c;所以为了提高CPU使用率&#xff0c;我有两个方案&#xff1a;一个是简单的梳理将任务可并行的采用并行流、额外线程池等方式做并行&#xff1b;另外…...

对回调函数的各种讲解说明

有没有跟我师弟一样的童靴~&#xff0c;学习和使用ROS节点时&#xff0c;对其中的callback函数一直摸不着头脑的&#xff0c;以下这么多回调函数的讲解&#xff0c;挨个看&#xff0c;你总会懂的O.o 回调函数怎么调用,如何定义回调函数&#xff1a; 回调函数怎么调用,如何定义…...

Java多线程:创建多线程的三种方式

在Java中&#xff0c;有三种方式创建多线程&#xff0c;继承类Thread&#xff0c;继承接口Runnable&#xff0c;继承接口Callable。其中Thread和Runnable需要重写方法run&#xff0c;方法run没有返回值&#xff1b;Callable需要重写方法call&#xff0c;方法call可以返回值。 …...

Unity中打印信息的两种方式

不继承MonoBehaviour的普通C#类中打印信息&#xff1a; 使用Debug类的方法&#xff1a; Unity提供了Debug类&#xff0c;其中包含了一些用于打印信息的静态方法。以下是常用的几种方法&#xff1a; Debug.Log(message)&#xff1a;打印普通信息。Debug.LogWarning(message)&a…...

给定n个字符串s[1...n], 求有多少个数对(i, j), 满足i < j 且 s[i] + s[j] == s[j] + s[i]?

题目 思路&#xff1a; 对于字符串a&#xff0c;b, (a.size() < b.size()), 考虑对字符串b满足什么条件&#xff1a; 由1、3可知a是b的前后缀&#xff0c;由2知b有一个周期是3&#xff0c;即a.size()&#xff0c;所以b是用多个a拼接而成的&#xff0c;有因为a是b的前后缀&…...

Linux磁盘空间与文件大小查看命令详解

1. 查看磁盘空间大小 在Linux系统中&#xff0c;有多个命令可以用来查看磁盘空间的使用情况。最常用的命令是df&#xff08;disk free&#xff09;。 df -hdf命令的 -h 选项以人类可读的方式显示磁盘空间&#xff0c;该命令将显示文件系统的使用情况、剩余空间等信息。 2. 查看…...

网络通信过程的一些基础问题

客户端A在和服务器进行TCP/IP通信时&#xff0c;发送和接收数据使用的是同一个端口吗&#xff1f; 这个问题可以这样来思考&#xff1a;在客户端A与服务器B建立连接时&#xff0c;A需要指定一个端口a向服务器发送数据。当服务器接收到A的报文时&#xff0c;从报文头部解析出A的…...

STL——stack容器和queue容器详解

目录 &#x1f4a1;stack &#x1f4a1;基本概念 常用接口 &#x1f4a1;queue &#x1f4a1;基本概念 &#x1f4a1;常用接口 &#x1f4a1;stack &#x1f4a1;基本概念 栈&#xff08;stack&#xff09;&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)

注&#xff1a;文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件&#xff1a;STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...