QCustomPlot的使用之四-响应鼠标移动和弹起事件

在项目中使用QCustomPlot过程中,会有新的需求需要满足,比如在显示的数据表格中,鼠标移动到数据线上的时候,需要实时显示当前显示的线上点的具体数据;点击这条线的时候,弹出对话框展现出数据线段的详细信息。

解决思路:在不改变QCustomPlot的前提下,在其外层封装一层类,使其外层实现相应的功能。
需要到的类图继续关系图:
在这里插入图片描述
先看实现的效果:
在这里插入图片描述

首先要找到QCustomPlot的相应的鼠标信息:鼠标移动和鼠标弹起。

void QCustomPlot::mouseMoveEvent(QMouseEvent *event) {
	emit mouseMove(event);

	if (!mMouseHasMoved && (mMousePressPos - event->pos()).manhattanLength() > 3)
		mMouseHasMoved = true; // moved too far from mouse press position, don't handle as click on mouse release

	if (mSelectionRect && mSelectionRect->isActive())
		mSelectionRect->moveSelection(event);
	else if (mMouseEventLayerable) // call event of affected layerable:
		mMouseEventLayerable->mouseMoveEvent(event, mMousePressPos);

	event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event.
}

void QCustomPlot::mouseReleaseEvent(QMouseEvent *event) {
	emit mouseRelease(event);

	if (!mMouseHasMoved) // mouse hasn't moved (much) between press and release, so handle as click
	{
		if (mSelectionRect && mSelectionRect->isActive()) // a simple click shouldn't successfully finish a selection rect, so cancel it here
			mSelectionRect->cancel();
		if (event->button() == Qt::LeftButton)
			processPointSelection(event);
...

在鼠标弹起事情中可以看到,当按键书鼠标左键的时候调用函数

processPointSelection(event);

然后看看这个函数的定义:

void QCustomPlot::processPointSelection(QMouseEvent *event) {
	QVariant details;
	QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details);
	...

通过调用layerableAt(event->pos(), true, &details);来获取当前鼠标选中的是哪个图层,返回值就是选中的图层。既然已经找到了选中的图层,剩下的就是做出相应判断了,但是咱们的前提是不能在文件中修改,所用需要重新定义一个新类继承自QCustomPlot;

class MYCUSTOMPLOT_EXPORT MyCustomPlot :public QCustomPlot {
public:
	MyCustomPlot();

	//注册鼠标操作
	void registerMouse(IPlotMouse* mouse);
private:
	virtual void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
	virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
	virtual void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
private:
	IPlotMouse* _mousePlot = nullptr;
};

MyCustomPlot::MyCustomPlot()
:QCustomPlot(nullptr) {
}

void MyCustomPlot::registerMouse(IPlotMouse* mouse) {
	_mousePlot = mouse;
}

void MyCustomPlot::mousePressEvent(QMouseEvent *event) {
	QCustomPlot::mousePressEvent(event);
}

void MyCustomPlot::mouseMoveEvent(QMouseEvent *event) {
	QCustomPlot::mouseMoveEvent(event);

	QVariant details;
	QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details);

	if (clickedLayerable != nullptr) {
		double xValue = 0.0;
		double yValue = 0.0;
		if (dynamic_cast<QCPGraph*>(clickedLayerable) != 0) {
			((QCPGraph*)clickedLayerable)->pixelsToCoords(event->pos(), xValue, yValue);
			if (_mousePlot != nullptr){
				_mousePlot->plotMouseMove(event->pos().x(), event->pos().y(), xValue, yValue, (QCPGraph*)clickedLayerable);
			}
		}
	}
}

void MyCustomPlot::mouseReleaseEvent(QMouseEvent *event) {
	QCustomPlot::mouseReleaseEvent(event);

	if (event->button() == Qt::LeftButton) {
		QVariant details;
		QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details);

		if (clickedLayerable != nullptr) {
			double xValue = 0.0;
			double yValue = 0.0;
			if (dynamic_cast<QCPGraph*>(clickedLayerable) != 0) {
				((QCPGraph*)clickedLayerable)->pixelsToCoords(event->pos(), xValue, yValue);
				if (_mousePlot != nullptr) {
					_mousePlot->plotMouseRelease(event->pos().x(), event->pos().y(), xValue, yValue, (QCPGraph*)clickedLayerable);
				}
			}
		}
	}
}

新类已经定义完了,新类中同样也需要实现鼠标事情:

	virtual void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
	virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
	virtual void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

在实现自定义类的鼠标函数中,首先要调用QCustomPlot中的鼠标函数,之后才可以实现自己新添加的功能。

在新添加的类中,注册了一个新的接口,这个接口用来对外通信的。比如我想让其他的界面响应鼠标事件,就需要其他的界面来继承这个接口并且实现相应的接口函数。如果不要相应那就不用调用下面这个注册函数就可以了

//注册鼠标操作
	void registerMouse(IPlotMouse* mouse);

注册接口:

_horRightAnglePlot = new /*QCustomPlot*/MyCustomPlot;
	_horRightAnglePlot->registerMouse(this);

实现接口响应:

void RadarDirectGraph::plotMouseRelease(double xPixel, double yPixel, double xValue, double yValue, void*graph) {
	QtGuiDirectDetail* guiDetail = new QtGuiDirectDetail;
	guiDetail->show();
}

void RadarDirectGraph::plotMouseMove(double xPixel, double yPixel, double xValue, double yValue, void*graph) {
	QString msg = QStringLiteral("(%1:%2)").arg(xValue).arg(yValue);
	QToolTip::showText(QCursor::pos(), msg);
}

aaa

Link-Riley曲线是一种常用于滤波器设计中的图形,可以使用QCustomPlot库在QT中绘制。以下是绘制Link-Riley曲线的步骤: 1. 在QT中创建一个QWidget或QMainWindow窗口,并在该窗口中添加QCustomPlot小部件。 2. 将以下代码添加到QWidget或QMainWindow的槽函数中,以绘制Link-Riley曲线: ``` QCustomPlot *customPlot = ui->customPlot; // 获取QCustomPlot小部件的指针 customPlot->addGraph(); // 添加一个图形 customPlot->graph(0)->setPen(QPen(Qt::blue)); // 设置曲线的颜色 customPlot->graph(0)->setName("Link-Riley Curve"); // 设置曲线的名称 QVector<double> x(101), y(101); // 设置xy向量 for (int i=0; i<101; i++) { double f = i/50.0; // 设置频率 double w = 2*M_PI*f; // 计算角频率 double a = 1/(1 + 0.414*pow(w, -1.0/2) + 0.707*pow(w, -1.0)); // 计算幅度响应 double phi = -atan(0.414*pow(w, -1.0/2) + 0.707*pow(w, -1.0)); // 计算相位响应 x[i] = f; // 设置x值 y[i] = 20*log10(a); // 计算dB值 } customPlot->graph(0)->setData(x, y); // 设置曲线的数据 customPlot->xAxis->setLabel("Frequency (Hz)"); // 设置x轴标签 customPlot->yAxis->setLabel("Magnitude (dB)"); // 设置y轴标签 customPlot->rescaleAxes(); // 自动缩放坐标轴 customPlot->replot(); // 绘制曲线 ``` 这段代码将在QCustomPlot小部件中添加一个蓝色的Link-Riley曲线。在这里,我们使用了Link-Riley滤波器的幅度响应相位响应计算公式来计算曲线的值。在这里,我们使用了dB值来表示曲线的幅度。 3. 运行QT程序,即可看到绘制的Link-Riley曲线。可以使用QCustomPlot库的其他函数来更改曲线的样式、添加标签、设置坐标轴等。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值