Выбор QLineSeries в QChartView с помощью выбора резиновой ленты - PullRequest
0 голосов
/ 21 мая 2018

У меня есть QChart с несколькими QLineSeries.

Я создал свой собственный класс диаграммы CPlotView, очищенный от QChartView, и переопределил mousePressEvent, mouseMoveEvent и mouseReleaseEvent, как показано ниже.

Я хочу реализовать и масштабирование с резиновой лентой, и выбор резиновой ленты по отдельности, и я могу выбрать, что делать, основываясь на проверяемых QPushButtons (код не показан, но это просто элемент CPlotView, который содержит значение перечисления, которое определяет, в каком «режиме» он находится (Zoom или Select)

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 внутри прямоугольника резиновой ленты (IЯ надеюсь, что это то, что возвращает QGraphicsView::items(PlotRubberBand->rect(), Qt::IntersectsItemShape);), но я не знаю, как определить мой ряд данных(У меня на самом деле есть смесь QLineSeries и QScatterSeries.

Есть некоторые QGraphicsItems, возвращаемые QGraphicsView::items(PlotRubberBand->rect(), Qt::IntersectsItemShape);, даже когда я не пересекаю резинку с какими-либо из моих данных, поэтому она, очевидно, возвращает некоторые другиепредметы на сцене.

Я пытался сделать dynamic_cast того, что возвращается QGraphicsView::items в QLineSeries, но это не сработало.Я не могу помочь, но думаю, что я делаю это более сложным, чем это должно быть.

ОБНОВЛЕНИЕ 1: Я также пытался захватывать сигналы, запускаемые при наведении курсора мыши на ряд данных во времярезиновая полоса выбирается с помощью:

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

, но сигнал не срабатывает при перетаскивании резиновой ленты (возможно, когда левая кнопка мыши нажата, она не срабатывает?).: (

ОБНОВЛЕНИЕ 2: Я попытался установить selectionArea в вызове mouseReleaseEvent (), и, опять же, некоторые из них возвращаются как выбранные, гораздо меньше, чем вызов 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 голосов
/ 22 января 2019

"Я пытался сделать dynamic_cast того, что возвращается QGraphicsView :: items для QLineSeries, но это не сработало."

Вот как я получаю представление QGraphicsItemQLineSeries.

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());
0 голосов
/ 19 июля 2018

Проблема, с которой вы столкнулись, заключается в том, что при включении режима резиновой ленты QChartView повторно реализует MousePressEvent и принимает событие.Поскольку события распространяются только вверх, QLineSeries (дочерний элемент QChart и QChartView) никогда не получает памятку.

Решение состоит в том, чтобы установить QEventFilter, чтобы вы могли перехватить событие до того, как QChartView его примет;тем не менее, я не выяснил, как определить, действительно ли был нажат QLineSeries.

...