欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

QCustomPlot之光标划过曲线显示点的坐标

程序员文章站 2022-06-13 21:20:41
...

在网上查了这方面的内容,几乎清一色的都是主要用QCPItemTracer和QCPItemText这两个类实现的,实现代码冗长,现在的我还没有搞懂。最后,发现通过QToolTip实现该功能是个挺简便的方法,能实现一个函数就搞定了,保证了代码的轻量级,随拿随用,下面就给出代码实现(qt 5.13 +vs2017+ C++)。
(1)首先建立一个鼠标移动时间响应函数:

private slots:
	void myMouseMoveEvent(QMouseEvent *event);

(2)将槽函数myMouseMoveEvent与QCustomPlot的mouseMove信号建立连接。
Plus,这里推荐基于qt5的信号槽连接,因为编译时,基于qt4的connect不会检查信号和槽的参数以及槽函数正确与否,而基于qt5的connect会有这一个检查过程(原来遇见过基于qt4的槽函数没有响应的情况)。

connect(ui.customPlot, &QCustomPlot::mouseMove, this, &AnalysisWidget::myMouseMoveEvent);

(3)槽函数实现光标划过曲线显示点坐标功能。
代码有详细注释,这里就不详细讲解。

void AnalysisWidget::myMouseMoveEvent(QMouseEvent *event)
{
	if (ui.customPlot->graphCount() == 0)
		return;

	//获取鼠标坐标,相对父窗体坐标
	int x_pos = event->pos().x();
	int y_pos = event->pos().y();

	//鼠标坐标转化为CustomPlot内部坐标
	float x_val = ui.customPlot->xAxis->pixelToCoord(x_pos);
	float y_val = ui.customPlot->yAxis->pixelToCoord(y_pos);

	//通过坐标轴范围判断光标是否在点附近
	float x_begin = ui.customPlot->xAxis->range().lower;
	float x_end = ui.customPlot->xAxis->range().upper;
	float y_begin = ui.customPlot->yAxis->range().lower;
	float y_end = ui.customPlot->yAxis->range().upper;
	float x_tolerate = (x_end - x_begin) / 40;//光标与最近点距离在此范围内,便显示该最近点的值
	float y_tolerate = (y_end - y_begin) / 40;

	//判断有没有超出坐标轴范围
	if (x_val < x_begin || x_val > x_end)
		return;

	//通过x值查找离曲线最近的一个key值索引
	int index = 0;
	int index_left = ui.customPlot->graph(0)->findBegin(x_val, true);//左边最近的一个key值索引
	int index_right = ui.customPlot->graph(0)->findEnd(x_val, true);//右边
	float dif_left = abs(ui.customPlot->graph(0)->data()->at(index_left)->key - x_val);
	float dif_right = abs(ui.customPlot->graph(0)->data()->at(index_right)->key - x_val);
	if (dif_left < dif_right)
		index = index_left;
	else
		index = index_right;

	x_val = ui.customPlot->graph(0)->data()->at(index)->key;//通过得到的索引获取key值

	int graphIndex=0;//curve index closest to the cursor	
	float dx = abs(x_val - ui.customPlot->xAxis->pixelToCoord(x_pos));
	float dy= abs(ui.customPlot->graph(0)->data()->at(index)->value - y_val);

	//通过遍历每条曲线在index处的value值,得到离光标点最近的value及对应曲线索引
	for (int i = 0; i < ui.customPlot->xAxis->graphs().count(); i++)
	{	
		if (abs(ui.customPlot->graph(i)->data()->at(index)->value - y_val)<dy)
		{
			dy = abs(ui.customPlot->graph(i)->data()->at(index)->value - y_val);
			graphIndex = i;
		}		
	}

	QString strToolTip = "测量点" + QString::number(graphIndex + 1) + ": (";
	strToolTip += QString::number(x_val, 10, 4) + ", ";
	strToolTip += QString::number(ui.customPlot->graph(graphIndex)->data()->at(index)->value) + ")";

	//判断光标点与最近点的距离是否在设定范围内
	if (dy < y_tolerate && dx < x_tolerate)
		QToolTip::showText(cursor().pos(), strToolTip, ui.customPlot);
}

效果:
QCustomPlot之光标划过曲线显示点的坐标

相关标签: qt c++