首页 > 其他分享 >QCustomPlot多段y轴公用x轴、动态增加/移除曲线显示功能

QCustomPlot多段y轴公用x轴、动态增加/移除曲线显示功能

时间:2024-03-28 16:30:51浏览次数:36  
标签:plot poAxisY Qt axisRect QCustomPlot 移除 多段 QCPAxis channel

备注:
1、动态增加/移除坐标系;
2、多段y轴,共用同一个x轴;
3、x轴y轴数据同步,当放大缩小表格时;
4、通过定时器0.5s更新一次数据;

****亲,感觉不错的话点个赞哦****

在这里插入图片描述

一、项目中结合树形目录勾选框,进行动态增加和删除勾选框,通过定时器模拟数据进行显示

connect(m_treeWidget, &TreeDirectoryWidget::sig_itemCheckChange, this, &WdtCustomChart::SlotItemChange);
connect(m_data_timer, SIGNAL(timeout()), this, SLOT(SlotDataTimeOut()));
void WdtCustomChart::SlotItemChange(QString id, bool check)
{
    //根据树形目录勾选框是否勾选进行动态增加/移除坐标系
	if (check)
	{
		auto rows = m_plot->plotLayout()->rowCount();
		QCPAxisRect* axisRect = CreateQCPAxisRect(id);
		m_plot->plotLayout()->addElement(rows++, 0, axisRect);
		UpdateSettingCommonXaXisx();
		ConnectAllAxisx(true);	
	}
	else
	{
		//移除该通道坐标及曲线
		RemoveQCPAxisRect(id);
	}
	m_plot->replot();
}

void WdtCustomChart::SlotDataTimeOut()
{
	static double key = 0;; // 开始到现在的时间,单位
	for (auto& pair : m_channel_plots.toStdMap())
	{
		int value = qrand() % 20;
		auto channel = pair.first;
		auto graph = pair.second;
		graph->addData(key,value);
		if (m_channel_axises.contains(channel))
		{
			auto AxisRec = m_channel_axises.value(channel);
			//QCPAxis* poAxisY = AxisRec->axis(QCPAxis::atLeft);		//y轴
			//int upper = (int)(poAxisY->range().upper);

			//if (upper < value)
			//	poAxisY->setRangeUpper(value + 10);

			if (key > 20)
				AxisRec->axis(QCPAxis::atBottom)->setRange(key, 20, Qt::AlignRight);
		}
	}
	key+=0.5;
	//绘图
	m_plot->replot();
}

static const QColor colors[] =
{
	Qt::red,
	Qt::green,
	Qt::blue,
	Qt::cyan,
	Qt::magenta,
	Qt::gray,
	Qt::darkRed,
	Qt::darkGreen,
	Qt::darkBlue,
	Qt::darkCyan,
};

二、核心代码:

1、动态增加channel所对应的坐标系

QCPAxisRect* WdtCustomChart::CreateQCPAxisRect(QString channel)
{
    //channel代表坐标系id
	QCPAxisRect* axisRect = new QCPAxisRect(m_plot, true);		
	axisRect->setupFullAxesBox(true);
	axisRect->setRangeZoom(Qt::Horizontal | Qt::Vertical); 
	QCPAxis* poAxisX = axisRect->axis(QCPAxis::atBottom);	//x轴
	QCPAxis* poAxisY = axisRect->axis(QCPAxis::atLeft);		//y轴
	poAxisX->setRange(0, 20);
	poAxisY->setRange(0, 50);
	axisRect->axis(QCPAxis::atTop)->setVisible(false);
	axisRect->axis(QCPAxis::atRight)->setVisible(false);
	poAxisX->grid()->setSubGridVisible(true);
	poAxisY->grid()->setSubGridVisible(true);
	axisRect->setAutoMargins(QCP::msRight | QCP::msLeft);
	axisRect->setMargins(QMargins(100, 0, 0, 0));
	poAxisY->setPadding(5); // 这里的5是你想要的额外填充
	poAxisY->setTickLabelPadding(10); // 这里的5是你想要的额外填充
	poAxisY->setLabelPadding(10); // 这里的5是你想要的额外填充
	poAxisX->setVisible(true);
	poAxisX->setLabel(Trans("时间(s)"));

	//设置x轴y轴自由缩放
	QList<QCPAxis*> aaxisField;
	aaxisField << poAxisX;
	aaxisField << poAxisY;
	axisRect->setRangeZoomAxes(aaxisField);
	
	poAxisY->setVisible(true);
	poAxisY->setLabel(Trans("通道") + channel);
	auto poGraph = m_plot->addGraph(poAxisX, poAxisY);
	QPen pen;
	pen.setColor(colors[qrand() % 10]);
	poGraph->setPen(pen);

	//下面这两行使得Y轴轴线总是对齐
	axisRect->setAutoMargins(QCP::MarginSide::msLeft | QCP::MarginSide::msRight);
	m_channel_axises.insert(channel.toInt(), axisRect);
	m_channel_plots.insert(channel.toInt(), poGraph);
	return axisRect;
}

2、动态删除channel所对应的坐标系

void WdtCustomChart::RemoveQCPAxisRect(QString channel)
{
	if (m_channel_axises.contains(channel.toInt()) && m_channel_plots.contains(channel.toInt()))
	{
		auto axes_rect = m_channel_axises.value(channel.toInt());
		auto graph_plot = m_channel_plots.value(channel.toInt());
		m_plot->plotLayout()->remove(axes_rect);
		m_plot->plotLayout()->simplify();
		m_channel_axises.remove(channel.toInt());
		m_channel_plots.remove(channel.toInt());
	}
}

3、//多段y轴共用同一个x轴

void WdtCustomChart::UpdateSettingCommonXaXisx()
{
	auto elements = m_plot->plotLayout()->elementCount();
	for (int row = 0; row < elements; row++)
	{
		QCPAxisRect* poRecti = (QCPAxisRect*)m_plot->plotLayout()->element(row, 0);
		if (poRecti)
		{
			//布局中最后一个元素进行设置
			if (row == (elements - 1))
			{
				poRecti->setMargins(QMargins(100, 0, 0, 40));
				poRecti->axis(QCPAxis::atBottom)->setVisible(true);
			}
			else
			{
				poRecti->setMargins(QMargins(100, 0, 0, 0));
				poRecti->axis(QCPAxis::atBottom)->setVisible(false);
			}
		}
	}
}

4、//当鼠标放大缩小上下移动时 ,多段y轴x轴同步

void WdtCustomChart::ConnectAllAxisx(bool on)
{
	auto elements = m_plot->plotLayout()->elementCount();
	for (int i = 0; i < elements; i++)
	{
		QCPAxisRect* poRecti = (QCPAxisRect*)m_plot->plotLayout()->element(i, 0);
		for (int j = 0; j < elements; j++)
		{
			QCPAxisRect* poRectj = (QCPAxisRect*)m_plot->plotLayout()->element(j, 0);
			if (poRectj && poRecti && i!=j)
			{
				connect(poRecti->axis(QCPAxis::atBottom), QOverload<const QCPRange&>::of(&QCPAxis::rangeChanged),
					poRectj->axis(QCPAxis::atBottom), QOverload<const QCPRange&>::of(&QCPAxis::setRange));
				connect(poRecti->axis(QCPAxis::atLeft), QOverload<const QCPRange&>::of(&QCPAxis::rangeChanged),
					poRectj->axis(QCPAxis::atLeft), QOverload<const QCPRange&>::of(&QCPAxis::setRange));
			}
		}
	}
}

5、初始化QCustomPlot

void WdtCustomChart::initPlot()
{

	m_plot = new QCustomPlot(this);
	m_plot->plotLayout()->clear();
	 允许用户用鼠标拖动轴范围,以鼠标为中心滚轮缩放,点击选择图形:
	m_plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
}

标签:plot,poAxisY,Qt,axisRect,QCustomPlot,移除,多段,QCPAxis,channel
From: https://blog.csdn.net/weixin_45074487/article/details/137076400

相关文章