Qt4+Qcustomplot绘制点后,移动鼠标显示鼠标最近的数据点信息。工作学习记录。

        本文用于工作时遇到问题的学习记录 

        情景是在使用Qcustomplot绘制了多条散点后,目标是移动鼠标,在靠近绘制的散点时显示对应的散点信息。我的项目限定是只显示选定的一条散点的信息,通过点击图例或散点进行选定。代码不全

//HandleMouseMoveEvent是我自定义的,当然可以直接调Qt的鼠标事件

// ui.chartView是我调用Qcustomplot的界面

void HandleMouseMoveEvent(QMouseEvent* event)
{
    //有多条散点
    for (int i = 0; i < ui.chartView->graphCount(); ++i)
    {

        //图例的选中联动,之前代码我已经实现。条件:需选中对应图例才显示散点
        QCPGraph* graphItem = ui.chartView->graph(i);
        if (graphItem->selected())
        {    
            // 获取鼠标相对于图形的位置
            QPointF pos = event->pos();
            // 将坐标转换到图形坐标系
            qreal xCoord = ui.chartView->xAxis->pixelToCoord(pos.x());
            qreal yCoord = ui.chartView->yAxis->pixelToCoord(pos.y());

            //记录X轴和Y轴的大小。目标:实现远离点时,不显示点的信息

            double visibleWidth = ui.chartView->xAxis->range().size();
            double visibleHeight = ui.chartView->yAxis->range().size();

            // 分别根据可视区域的大小来估算水平和垂直方向的阈值,根据需要修改暂时都 *0.05
            double horizontalThreshold = visibleWidth * 0.05;
            double verticalThreshold = visibleHeight * 0.05; 

            // 找到离鼠标位置最近的数据点
            double minDistance = std::numeric_limits<double>::max();
            //设置最近点的index为-1

            int nearestPointIndex = -1;

            //读取graph中绘制的散点,找到最近点的index
            for (int j = 0; j < ui.chartView->graph(i)->dataCount(); ++j) {
                double horizontalDistance = qAbs(xCoord - ui.chartView->graph(i)->data()->at(j)->key);
                double verticalDistance = qAbs(yCoord - ui.chartView->graph(i)->data()->at(j)->value);
                double totalDistance = qSqrt(qPow(horizontalDistance, 2) + qPow(verticalDistance, 2));
                if (horizontalDistance <= horizontalThreshold &&
                    verticalDistance <= verticalThreshold &&
                    totalDistance < minDistance) {
                        minDistance = totalDistance;
                        nearestPointIndex = j;
                }
            }

            if (nearestPointIndex != -1) { 

                QDebug()<<"X:"<<ui.chartView->graph(i)->data()->at(nearestPointIndex)->key;

                QDebug()<<"Y:"<<ui.chartView->graph(i)->data()->at(nearestPointIndex)->value;
              
            } else {
                    //设置不显示点
            }
        }
    }
}

请多多指教^_^!;

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现动态曲线的绘制鼠标悬停显示数据,可以使用QCustomPlot库。 首先,创建一个QCustomPlot对象,并设置x轴和y轴的范围: ```cpp QCustomPlot *plot = new QCustomPlot(this); plot->xAxis->setRange(0, 10); plot->yAxis->setRange(-1, 1); ``` 然后,添加一条曲线并设置其属性: ```cpp QCPGraph *graph = plot->addGraph(); graph->setPen(QPen(Qt::blue)); graph->setAntialiasedFill(false); ``` 接下来,在定时器中不断更新曲线的数据,并调用replot()函数刷新图表: ```cpp QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [plot, graph]() { static double phase = 0; QVector<double> x(101), y(101); for (int i = 0; i < 101; ++i) { x[i] = i / 10.0; y[i] = qSin(x[i]*2*M_PI + phase); } graph->setData(x, y); plot->replot(); phase += 0.1; }); timer->start(50); ``` 最后,实现鼠标悬停显示数据的功能,可以使用QCPItemTracer类,它可以跟踪曲线上某个的坐标,并在鼠标悬停时显示数据: ```cpp QCPItemTracer *tracer = new QCPItemTracer(plot); tracer->setGraph(graph); tracer->setStyle(QCPItemTracer::tsCircle); tracer->setPen(QPen(Qt::red)); tracer->setBrush(Qt::white); tracer->setSize(10); tracer->setVisible(false); connect(plot, &QCustomPlot::mouseMove, this, [plot, tracer](QMouseEvent *event) { QPointF pos = plot->mapToValue(event->pos()); double x = pos.x(); double y = graph->data()->value(x); if (!qIsNaN(y)) { tracer->setVisible(true); tracer->setGraphKey(x); tracer->updatePosition(); QString text = QString("x=%1, y=%2").arg(x).arg(y); QToolTip::showText(event->globalPos(), text, plot); } else { tracer->setVisible(false); QToolTip::hideText(); } }); ``` 完整的示例代码如下: ```cpp #include <QApplication> #include <QMainWindow> #include <QCustomPlot> int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow window; QCustomPlot *plot = new QCustomPlot(&window); plot->xAxis->setRange(0, 10); plot->yAxis->setRange(-1, 1); QCPGraph *graph = plot->addGraph(); graph->setPen(QPen(Qt::blue)); graph->setAntialiasedFill(false); QCPItemTracer *tracer = new QCPItemTracer(plot); tracer->setGraph(graph); tracer->setStyle(QCPItemTracer::tsCircle); tracer->setPen(QPen(Qt::red)); tracer->setBrush(Qt::white); tracer->setSize(10); tracer->setVisible(false); connect(plot, &QCustomPlot::mouseMove, &window, [plot, tracer](QMouseEvent *event) { QPointF pos = plot->mapToValue(event->pos()); double x = pos.x(); double y = graph->data()->value(x); if (!qIsNaN(y)) { tracer->setVisible(true); tracer->setGraphKey(x); tracer->updatePosition(); QString text = QString("x=%1, y=%2").arg(x).arg(y); QToolTip::showText(event->globalPos(), text, plot); } else { tracer->setVisible(false); QToolTip::hideText(); } }); QTimer *timer = new QTimer(&window); connect(timer, &QTimer::timeout, &window, [plot, graph]() { static double phase = 0; QVector<double> x(101), y(101); for (int i = 0; i < 101; ++i) { x[i] = i / 10.0; y[i] = qSin(x[i]*2*M_PI + phase); } graph->setData(x, y); plot->replot(); phase += 0.1; }); timer->start(50); window.setCentralWidget(plot); window.resize(800, 600); window.show(); return a.exec(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值