Search code examples
c++qtqt5qtcharts

Scale x-axis of QChartView using mouse wheel


In my application I use QChart to show line graph. Unfortunately Qt Charts doesn't support such basic functions as zooming using mouse wheel and scrolling by mouse. Yes, there is RubberBand functionality but that still doesn't support scrolling etc end that isn't so intuitive to users. Also I need to scale only x-axis, some kind of setRubberBand(QChartView::HorizontalRubberBand) but using mouse wheel. So far, after diving into QChartView I've use the following workaround:

class ChartView : public QChartView {
protected:
    void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
    {
        QRectF rect = chart()->plotArea();            
        if(event->angleDelta().y() > 0)
        {
            rect.setX(rect.x() + rect.width() / 4);
            rect.setWidth(rect.width() / 2);                                   
        }
        else
        {
            qreal adjustment = rect.width() / 2;
            rect.adjust(-adjustment, 0, adjustment, 0);                    
        }            
        chart()->zoomIn(rect);
        event->accept();            
        QChartView::wheelEvent(event);
    }
}

That works but zooming in and then zooming out doesn't lead to the same result. There is a small deviation. After debuging I've found that chart()->plotArea() always returns the same rect, so this workaround was useless.

It there some way to get rect of a visible area only? Or may be someone could point me to the right solution how to do zooming/scrolling by mouse for QChartView?


Solution

  • Instead of using zoomIn() and zoomOut() you could use zoom() as shown below:

    class ChartView : public QChartView {
    protected:
        void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
        {
            qreal factor = event->angleDelta().y() > 0? 0.5: 2.0;
            chart()->zoom(factor);
            event->accept();
            QChartView::wheelEvent(event);
        }
    };
    

    Regarding zoomIn() and zoomOut(), it is not clear to what kind of coordinates it refers, I am still investing, when I have more information I will update my answer.

    update:

    As I observe one of the problems is the multiplication of floating point, and the other is to locate the center of the figure, to not have those problems my solution resets the zoom and then sets the change:

    class ChartView : public QChartView {
        qreal mFactor=1.0;
    protected:
        void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
        {
            chart()->zoomReset();
    
            mFactor *= event->angleDelta().y() > 0 ? 0.5 : 2;
    
            QRectF rect = chart()->plotArea();
            QPointF c = chart()->plotArea().center();
            rect.setWidth(mFactor*rect.width());
            rect.moveCenter(c);
            chart()->zoomIn(rect);
    
            QChartView::wheelEvent(event);
        }
    };