IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Customplot画多条折线图,同时可以控制每条曲线的隐藏和显示 -> 正文阅读

[C++知识库]Customplot画多条折线图,同时可以控制每条曲线的隐藏和显示

Customplot多条曲线的控制

前言

	开始使用Qcharts画图,大数据性能极差。于是转用Customplot画图,主要进行数据的实时更新和大量数据的加载

一、模拟数据

	采用子线程创建模拟数据,采用队列存储。
#pragma once

#include <QThread>
#include<QQueue>
#include<QMap>
#include<QMutex>
#include<QPointF>
#include<QVariant>
using namespace std;
class QTgui : public QThread
{
	Q_OBJECT
signals:
	void sigCurrentImage1(QVariant img);
public:
	QTgui(QObject *parent = nullptr);
	~QTgui();
	std::thread * tthread;
	void run();
	void SetRandNum();
private:
	int a;
	QString data;
	QMutex tex;
	QMap<QString, QQueue<QPointF>> datamap;//key 设备名称 value 点
};

#include "QTgui .h"
#include <QDebug>
#include <QThread>
#include <QTime>
#include<QQueue>
#include<QMap>
QTgui::QTgui(QObject *parent)
	: QThread(parent)
{
	a = 0;
}

QTgui ::~QTgui()
{

}
void QTgui::run()
{
	qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
	//point = new QQueue<QPointF>();
	// 要想线程一直运行 就用 while  不会运行一次就结束了
	while (1)
	{
		SetRandNum();
		QVariant var;
		var.setValue(datamap);
		emit sigCurrentImage1(var);
		this_thread::sleep_for(std::chrono::milliseconds(1000));

	}

}
void QTgui::SetRandNum()
{
	for (int i = 0; i < 1; i++)
	{
		for (int j = 0; j < 3600; j++)
		{
			QTime time(QTime::currentTime());
			int nowtime = time.msecsSinceStartOfDay();
			QPointF currentpoint = QPointF(nowtime, qrand() % 101);
			if (datamap.count(QString::number(i)) > 0)
			{
				if (datamap[QString::number(i)].size() > 3600)
				{
					datamap[QString::number(i)].dequeue();
					datamap[QString::number(i)].enqueue(currentpoint);
				}
				else
				{
					datamap[QString::number(i)].enqueue(currentpoint);
				}
			}
			else
			{
				QQueue<QPointF> dataqueue;
				dataqueue.enqueue(currentpoint);
				datamap.insert(QString::number(i), dataqueue);
			}
		}
		//QTime time(QTime::currentTime());
		//int nowtime = time.msecsSinceStartOfDay();
		//QPointF currentpoint = QPointF(nowtime, qrand() % 101);
		//if (datamap.count(QString::number(i)) > 0)
		//{
		//	if (datamap[QString::number(i)].size() > 1000000)
		//	{
		//		datamap[QString::number(i)].dequeue();
		//		datamap[QString::number(i)].enqueue(currentpoint);
		//	}
		//	else
		//	{
		//		datamap[QString::number(i)].enqueue(currentpoint);
		//	}
		//}
		//else
		//{
		//	QQueue<QPointF> dataqueue;
		//	dataqueue.enqueue(currentpoint);
		//	datamap.insert(QString::number(i), dataqueue);
		//}
		auto aa = 0;
	}

}
数据有坐标点和时间点2种,测试注释掉了时间点。

二、主界面槽函数绑定

主要用于连接数据线程和UI槽函数的连接。

#pragma once
#include<QPointF>
#include <QtWidgets/QWidget>
#include "ui_QtWidgetsApplication7.h"
#include "QTgui .h"
#include<QQueue>
#include<QMap>
class QtWidgetsApplication7 : public QMainWindow
{
    Q_OBJECT
public:
    QtWidgetsApplication7(QWidget *parent = Q_NULLPTR);
	void Init();
	~QtWidgetsApplication7();
	QTgui* g1;
signals:
	void SendData(QMap<QString, QQueue<QPointF>> data);//发送数据
private:
    Ui::QtWidgetsApplication7Class ui;
	int a = 1;
private slots:
	void slot2(QVariant data);
};

#include "QtWidgetsApplication7.h"
#include"qcustomplot.h"
#include"LineChartTest.h"
#if _MSC_VER >= 1600 //VS2015>VS>VS2010, MSVC VER= 10.0 -14.0 防止乱码
#pragma execution_character_set("utf-8")
#endif
QtWidgetsApplication7::QtWidgetsApplication7(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
	Init();

}
void QtWidgetsApplication7::Init()
{
	g1 = new QTgui(this);
	g1->start();
	connect(g1, SIGNAL(sigCurrentImage1(QVariant)), this, SLOT(slot2(QVariant)));
	LineChartTest *cht = new LineChartTest(this);
	connect(this, SIGNAL(SendData(QMap<QString, QQueue<QPointF>>)), cht, SLOT(ShowData(QMap<QString, QQueue<QPointF>>)));
	connect(this, SIGNAL(SendData(QMap<QString, QQueue<QPointF>>)), cht, SLOT(Run(QMap<QString, QQueue<QPointF>>)));
	QVBoxLayout *layout3 = new QVBoxLayout();
	layout3->addWidget(cht);
	ui.widget->setLayout(layout3);
}
QtWidgetsApplication7::~QtWidgetsApplication7()
{
	g1->terminate();//主动结束线程
	g1->deleteLater();
}


void QtWidgetsApplication7::slot2(QVariant data)
{
	ui.label->setText(QString::number(a++));
	QMap<QString, QQueue<QPointF>> d=data.value<QMap<QString, QQueue<QPointF>>>();
	SendData(d);

}

三、UI界面设置和显示

展示实时数据和更新界面。启用定时器更新界面。

#pragma once

#include <QtWidgets/QWidget>
#include "QTgui .h"
#include "ui_LineChartTest.h"
#include "QCustomPlot.h"
using namespace std;
class LineChartTest : public QWidget
{
	Q_OBJECT

public:
	LineChartTest(QWidget *parent = Q_NULLPTR);
	~LineChartTest();

	void initPlotForm();


	

public slots:
	void ShowData(QMap<QString, QQueue<QPointF>> a);
	void Show_Plot();

	void Run(QMap<QString, QQueue<QPointF>> data);
private:
	Ui::LineChartTest ui;
	int data;
	void ShowChart();
	QCustomPlot *customPlot;
	QCPGraph *series[32];//最多可以设置曲线数量
	QQueue<QPointF> point;
	QTimer *timer;
	bool status;//显示哪条折线
};

#include "LineChartTest.h"
#include <QWidget>
#include "QCustomPlot.h"
#pragma execution_character_set("utf-8")
LineChartTest::LineChartTest(QWidget *parent)
	: QWidget(parent), status(false)
{
	ui.setupUi(this);
	initPlotForm();
	//定时器更新图表
	timer = new QTimer();
	timer->start(200);
	connect(timer, SIGNAL(timeout()), this, SLOT(Show_Plot()));
	QThread *thd = new QThread();
	customPlot->moveToThread(thd);//其他图像操作放到子线程
	thd->start();
}
void LineChartTest::ShowChart()
{

}
LineChartTest::~LineChartTest()
{
	timer->deleteLater();
}
void LineChartTest::ShowData(QMap<QString, QQueue<QPointF>> getdata)
{

		
}
//初始化图表格式
void LineChartTest::initPlotForm()
{


	//隐藏标题栏
	this->setWindowFlags(Qt::FramelessWindowHint);
	this->setWindowState((windowState()&~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowMaximized);
	QVBoxLayout *layout = new QVBoxLayout();
	customPlot = new QCustomPlot(this);
	//QSharedPointer<QCPAxisTickerDateTime> dateTicker(new QCPAxisTickerDateTime);//日期做X轴
	//dateTicker->setDateTimeFormat("m:s");//日期格式(可参考QDateTime::fromString()函数)
	//customPlot->xAxis->setTicker(dateTicker);//设置X轴为时间轴
	//customPlot->xAxis->setRange(0, 3601);
	customPlot->xAxis->ticker()->setTickCount(37);//11个主刻度
	customPlot->xAxis->setLabel("X轴");//轴标签
	customPlot->yAxis->setLabel("Y轴");//轴标签
	customPlot->yAxis->setRange(-30, 200);
	customPlot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);//x轴终点箭头图案
	customPlot->xAxis->setLowerEnding(QCPLineEnding::esDisc);//x轴起点圆点图案
	customPlot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);//x轴起点圆点图案
	layout->addWidget(customPlot);
	customPlot->setOpenGl(true);
	customPlot->addGraph(0)->setPen(QPen(Qt::red));
	 // 允许用户用鼠标拖动轴范围,用鼠标滚轮缩放,点击选择图形:
	customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
	ui.widget->setLayout(layout);
}
void LineChartTest::Run(QMap<QString, QQueue<QPointF>> data)
{

		int nowtime = QTime::currentTime().msecsSinceStartOfDay(); // 当前时间总的毫秒数
		customPlot->clearGraphs();  //请清除所有
		customPlot->xAxis->rescale(true);//调整X轴的范围,使之能显示出所有的曲线的X值
		customPlot->yAxis->rescale(true);//调整Y轴的范围,使之能显示出所有的曲线的Y值
		customPlot->xAxis->setRange(0, data["0"].size());
		//series->setObjectName("温度1");
		series[0]= customPlot->addGraph();
		series[0]->setName("温度1");
		series[0]->setPen(QPen(Qt::red));
		series[1] = customPlot->addGraph();
		series[1]->setName("湿度1");
		series[1]->setPen(QPen(Qt::blue));
		for (int i = 0; i < data[QString::number(0)].size(); i++)
		{
			//给曲线添加数据
			//series->addData(data[QString::number(0)].at(i).x()*0.001, data[QString::number(0)].at(i).y());
			series[0]->addData(i, data[QString::number(0)].at(i).y());
			series[1]->addData(i, data[QString::number(0)].at(i).y()+50);
		}
		//this_thread::sleep_for(std::chrono::milliseconds(1));
}
//更新绘图 同时分别显示对应曲线
void LineChartTest::Show_Plot()
{
	if (status)
	{
		for (int i = 0; i < 2; i++)
		{
			if (series[i]->name() == "温度1")
			{
				series[i]->setVisible(false);
			}
		}
		status = !status;
	}
	else
	{
		for (int i = 0; i < 2; i++)
		{
			if (series[i]->name() == "湿度1")
			{
				series[i]->setVisible(false);
			}
		}
		status = !status;
	}
	customPlot->replot(QCustomPlot::rpQueuedReplot);
}

效果展示

在这里插入图片描述
下载地址:https://download.csdn.net/download/qq_38491692/85311194

总结

	本文主要介绍了一个基本的绘制曲线的流程,线程产生数据,定时更新。解决界面卡顿问题。
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:22:52  更:2022-05-09 12:24:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 23:37:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码