2

am trying to implement a custom graph going off the QtCharts Callout example. I want to restrict the selection of the chart to a specific area and make it possible to scroll horizontally while still displaying the Axis Values.

the classes i am using are below

callout.cpp

callout.h

main.cpp

view.cpp

view.h

here is an example of what i mean

say i want the selection region point1 = (5,0) point2 = (15,8) and the region is a QRect(point1,point2)

enter image description here enter image description here

All points in the graph should be rendered but I want to be able to scroll sideways and keep the y_axis in view.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
BigL
  • 165
  • 1
  • 2
  • 15
  • What do you mean by selection? You mean the user manually does it or just create a method that does it. What do you mean with Horizontal Scroll? Do you want a scrollbar or just dragging the mouse? – eyllanesc Jan 29 '20 at 17:12
  • I just want to create a method that does it. and just by dragging the mouse. – BigL Jan 30 '20 at 04:25

1 Answers1

0

One possible solution is to override the mousePressEvent and mouseMoveEvent methods to apply the scroll, and correct using the axes ranges if necessary:

#include <QtWidgets>
#include <QtCharts>

#include <algorithm>

QT_CHARTS_USE_NAMESPACE

class ChartView: public QChartView{
public:
    using QChartView::QChartView;
    void setRange(qreal xmin, qreal xmax, qreal ymin, qreal ymax){
        if(!chart()) return;
        if(QValueAxis *xaxis = qobject_cast<QValueAxis *>(chart()->axes(Qt::Horizontal).first())){
            xaxis->setRange(xmin, xmax);
        }
        if(QValueAxis *yaxis = qobject_cast<QValueAxis *>(chart()->axes(Qt::Vertical).first())){
            yaxis->setRange(ymin, ymax);
        }
    }
    void setLimits(qreal min, qreal max, Qt::Orientation orientation){
        m_limit_min = min;
        m_limit_max = max;
        m_orientation = orientation;
    }
protected:
    void mousePressEvent(QMouseEvent *event)
    {
        if (event->button() == Qt::LeftButton && chart())
            m_lastMousePos = mapToScene(event->pos());
        QGraphicsView::mousePressEvent(event);
    }
    void mouseMoveEvent(QMouseEvent *event)
    {
        if(event->buttons() & Qt::LeftButton && chart()){
            QPointF newValue = mapToScene(event->pos());
            QPointF delta = newValue - m_lastMousePos;
            if(m_orientation == Qt::Horizontal)
                chart()->scroll(-delta.x(), 0);
            else
                chart()->scroll(0, -delta.y());
            if(QValueAxis * axis = qobject_cast<QValueAxis *>(chart()->axes(m_orientation).first()) ){
                qreal deltaX = axis->max() - axis->min();
                if(axis->min() < m_limit_min){
                    axis->setRange(m_limit_min, m_limit_min + deltaX);
                }
                else if(axis->max() > m_limit_max){
                    axis->setRange(m_limit_max - deltaX, m_limit_max);
                }
            }
            m_lastMousePos = newValue;
        }
        QGraphicsView::mouseMoveEvent(event);
    }
private:
    QPointF m_lastMousePos;
    qreal m_limit_min;
    qreal m_limit_max;
    Qt::Orientation m_orientation;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    ChartView chartView;
    chartView.setRenderHint(QPainter::Antialiasing);
    chartView.resize(640, 480);

    QLineSeries *series = new QLineSeries();
    series->append(0, 6);
    series->append(2, 4);
    series->append(3, 8);
    series->append(7, 4);
    series->append(10, 5);
    *series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2);
    QChart *chart = chartView.chart();
    chart->legend()->hide();
    chart->addSeries(series);
    chart->createDefaultAxes();
    chartView.show();

    chartView.setRange(5, 15, 0, 8);
    chartView.setLimits(0, 20, Qt::Horizontal);

    return a.exec();
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241