使用橡皮带选择在QChartView中选择QLineSeries

时间:2018-05-21 12:13:43

标签: qt qchart qchartview

我有一个QChart,上面有许多QLineSeries。

我已经在QChartView中创建了自己的图表类CPlotView,并覆盖了mousePressEvent,mouseMoveEvent和mouseReleaseEvent,如下所示。

我想分别实施橡皮筋变焦和橡皮筋选择,我可以根据可检查的QPushButtons选择要做的事情(代码未显示,但它只是CPlotView的一个成员,其中包含一个枚举值,用于定义其中的'模式' (缩放或选择)

void CPlotView::mousePressEvent(QMouseEvent *event)
{
     if(PlotRubberBand)
     {
         if (PlotCursorMode == ECursorMode::eIsolate || PlotCursorMode == ECursorMode::eZoom)
         {
             QRectF plotArea = chart()->plotArea();
             if (PlotRubberBand->isEnabled()
                 && event->button() == Qt::LeftButton
                 && plotArea.contains(event->pos()))
             {

                 DrawRubberBand = true;
                 PlotRubberBandOrigin = event->pos();
                 PlotRubberBand->setVisible(true);
                 PlotRubberBand->setGeometry(QRect(PlotRubberBandOrigin, QSize()));
                 event->accept();
             }
             QGraphicsView::mousePressEvent(event);

         }
         else
         {
             QChartView::mousePressEvent(event);
         }
     }

    QChartView::mousePressEvent(event);
}

void CPlotView::mouseMoveEvent(QMouseEvent *event)
{
    if (GetPlotCursorMode() == ECursorMode::eIsolate)
    {
        if (DrawRubberBand && PlotRubberBand->isVisible())
        {
            QRect rect = chart()->plotArea().toRect();
            int width = event->pos().x() - PlotRubberBandOrigin.x();
            int height = event->pos().y() - PlotRubberBandOrigin.y();

            PlotRubberBand->setGeometry(QRect(PlotRubberBandOrigin.x(), PlotRubberBandOrigin.y(), width, height).normalized());

        }
        else
        {
             QGraphicsView::mouseMoveEvent(event);
        }
    }
    else if (GetPlotCursorMode() == ECursorMode::eZoom)
    {
        if (DrawRubberBand && PlotRubberBand->isVisible())
        {
            QChartView::mouseMoveEvent(event);
        }
        else
        {
            QGraphicsView::mouseMoveEvent(event);
        }
    }
    else if (GetPlotCursorMode() == ECursorMode::eSelect)
    {
        QGraphicsView::mouseMoveEvent(event);
    }
    else
    {
        QChartView::mouseMoveEvent(event);

    }

}

void CPlotView::mouseReleaseEvent(QMouseEvent *event)
{
    if (PlotRubberBand->isVisible())
    {
        if (PlotCursorMode == ECursorMode::eIsolate)
        {
             DrawRubberBand = false;
             PlotRubberBand->setVisible(false);

            QGraphicsView::mouseReleaseEvent(event);

            QList<QGraphicsItem *> selected_items = QGraphicsView::items(PlotRubberBand->rect(), Qt::IntersectsItemShape);

            qDebug() << "found " << selected_items.size() << " items"; // this appears to show a number of items, but how do I detect which items are my data series, if any are?
            for (auto& item : selected_items)
            {
                // detect which are my data series and highlight them as selected
            }

        }
        else
        {
            DrawRubberBand = false;
            PlotRubberBand->setVisible(false);
            QChartView::mouseReleaseEvent(event);
        }
    }
}

我现在可以使用缩放模式 - 单击“缩放”模式按钮,然后拖动绘图上的橡皮带缩放到该区域。单击选择模式按钮绘制橡皮带但不缩放。我现在想在选择模式下选择橡皮带中的所有数据系列。

在选择模式的mouseReleaseEvent中,我试图捕获橡皮带矩形内的所有选定QGraphicsItems(我希望这是QGraphicsView::items(PlotRubberBand->rect(), Qt::IntersectsItemShape);返回的内容),但我不知道我不知道如何检测我的数据系列(我实际上有QLineSeries和QScatterSeries的混合物。

即使我没有将橡皮带与我的任何数据相交,QGraphicsItems也会返回一些QGraphicsView::items(PlotRubberBand->rect(), Qt::IntersectsItemShape);,因此它显然会返回场景中的其他一些项目。

我尝试dynamic_castQGraphicsView::items返回的内容QLineSeries,但这不起作用。我不禁想到我让它变得比它应该更复杂。

UPDATE1:我还尝试捕捉鼠标在橡皮筋选择期间悬停在数据系列上时触发的信号:

connect(line_series, SIGNAL(hovered(const QPointF &, bool)), this, SLOT(OnDataHovered(const QPointF&, bool)));

但是当橡皮筋拖动时信号不会触发(可能当鼠标左键停止时它不会触发?)。 :(

更新2:我已经尝试在mouseReleaseEvent()调用中设置selectionArea,并且再一次将其中一些返回为选中,远远少于调用QGraphicsView::items(),但不是我的系列据我所知:

void ewbearinghistorychart::CEwBearingHistoryChartView::mouseReleaseEvent(QMouseEvent *event)
{
    if (PlotRubberBand->isVisible())
    {
        if (PlotCursorMode == ECursorMode::eIsolate)
        {
            DrawRubberBand = false;
            PlotRubberBand->setVisible(false);
            QRect rubberband_rect = PlotRubberBand->rect();
            QGraphicsView::mouseReleaseEvent(event);

            // ************** new code **************
            QPolygonF p = chart()->mapToScene(PlotRubberBand->rect().normalized());
            QPainterPath path;
            path.addPolygon(p);
            chart()->scene()->setSelectionArea(path, Qt::IntersectsItemShape);
            QList<QGraphicsItem *> selected_items = chart()->scene()->selectedItems();
            qDebug() << "selected items: " << selected_items.size();
            // ************** /new code **************                
        }
        else
        {
            DrawRubberBand = false;
            PlotRubberBand->setVisible(false);
            QChartView::mouseReleaseEvent(event);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您遇到的问题是,启用橡皮筋模式后,QChartView将重新实现MousePressEvent并接受事件。由于事件仅向上传播,因此QLineSeriesQChartQChartView的子代)永远不会获得备忘录。

解决方案是安装QEventFilter,以便您可以在QChartView接受事件之前拦截该事件;但是,我还没有弄清楚如何检测是否实际上是被点击的QLineSeries

答案 1 :(得分:0)

  

“我尝试对QGraphicsView :: items返回到QLineSeries的内容进行dynamic_cast,但这没用。”

这是如何获取QLineSeries的QGraphicsItem表示形式。

QChart        ch;
QLineSeries  srs;

QList<QGraphicsItem*> bf{ch.childItems()};
ch.addSeries(&srs);
QList<QGraphicsItem*> af{ch.childItems()};

QGraphicsItem * mf;

for(auto e: af)
    if(!bf.contains(e))
        mf = e;

qDebug().operator<<(mf->isUnderMouse());