2

I try to link the rubberBandChanged signal from QChartView class to a specific function in MainWindow class.

MainWindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public slots:
    void rubberZoomAdapt(QRect, QPointF, QPointF);

private:
    Ui::MainWindow *ui;
    QChartView* qcvChart;
    Chart* chart;
};

MainWindow.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    qcvChart(new QChartView),
    chart(new Chart)
{
    ui->setupUi(this);

    //Connexion
    QObject::connect(qobject_cast<QGraphicsView*>(this->qcvChart),
                     &QGraphicsView::rubberBandChanged,
                     this,
                     &MainWindow::rubberZoomAdapt);

    this->qcvChart->setChart(this->chart);
    this->qcvChart->setRubberBand(QChartView::HorizontalRubberBand);
}

void MainWindow::rubberZoomAdapt(QRect r, QPointF fp, QPointF tp)
{
    static int i = 0;
    qDebug() << "(rubberZoomAdapt) RubberBand Event: " << QString::number(i++);
}

When I use the rubberBand in my chart, I never enter in the rubberZoomAdapt().

Any idee to fix this ?

Thanks.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
falcon
  • 51
  • 8

1 Answers1

2

The problem is that although QChartView inherits from QGraphicsView it does not use the same QRubberBand so the rubberBandChanged signal is never issued.

The solution is to look for the QRubberBand since it is a child of QChartView and filter it through the resizeEvent event, and then create our own signal:

*.h

...
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    bool eventFilter(QObject *watched, QEvent *event) override;
public slots:
    void rubberZoomAdapt(QPointF fp, QPointF tp);

signals:
    void rubberBandChanged(QPointF fp, QPointF tp);

private:
    Ui::MainWindow *ui;
    QChartView* qcvChart;
    QChart* chart;
    QRubberBand *rubberBand;
};
...

*.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    qcvChart(new QChartView),
    chart(new QChart)
{
    ui->setupUi(this);

    qcvChart->setChart(chart);
    qcvChart->setRubberBand(QChartView::HorizontalRubberBand);
    rubberBand = qcvChart->findChild<QRubberBand *>();
    rubberBand->installEventFilter(this);

    connect(this, &MainWindow::rubberBandChanged,this, &MainWindow::rubberZoomAdapt);

    setCentralWidget(qcvChart);
    ...
}

...

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == rubberBand && event->type() == QEvent::Resize){
        QPointF fp = chart->mapToValue(rubberBand->geometry().topLeft());
        QPointF tp = chart->mapToValue(rubberBand->geometry().bottomRight());
        emit rubberBandChanged(fp, tp);
    }
    return QMainWindow::eventFilter(watched, event);
}

void MainWindow::rubberZoomAdapt(QPointF fp, QPointF tp)
{
    qDebug() << "(rubberZoomAdapt) RubberBand Event: "<<fp<<tp;
}

The complete example can be found in the following link

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank a lot for your answer. But I have an error with the "emit" line code: error: no matching function for call to 'MainWindow::rubberBandChanged(QPointF&, QPointF&)' emit rubberBandChanged(fp, tp); second thing, can you explain why you specify the "override" there: bool eventFilter(QObject *watched, QEvent *event) override; and last thing, why you install the event filter on MainWindow and not on the ChartView like this->installEventFilter(this->qcvChart); Can you help me again ? – falcon Mar 29 '18 at 08:48
  • Moreover, the line code: this->qRubberBand->installEventFilter(this); crash my application before she can even start. @eyllanesc – falcon Mar 29 '18 at 10:17
  • @falcon Are you using my example or are you adapting it for your code? if it is the latter, you must do this last, first stable the type of QRubberBand, then do the search and finally the connection; the order is important. – eyllanesc Mar 29 '18 at 10:41
  • @falcon If you check my answer I am creating a new custom signal, in my case I think it is not necessary to send the rectangle since I send the corners of the rectangle. using `override` is a good practice, please read the following to see its advantages https://stackoverflow.com/questions/18198314/what-is-the-override-keyword-in-c-used-for. Finally install the event filter in MainWindow for simplicity, I could do it in general in any other QObject without having problems. – eyllanesc Mar 29 '18 at 11:11
  • You can check my project I just creat a bitbucket repository: https://bitbucket.org/falcon1990/psimuvisu/src/f2734cbab3e2d7dc0d8177836a2af6d770efd6a5?at=master Connection are commented and interest class are ManWindow and maybe Chart. I will try your code in a new project. Thanks for helping me ! – falcon Mar 29 '18 at 12:08
  • @falcon The problem is that you are doing the search when the QRubberBand does not exist, you must do it when you enable it: `if(this->bCursorState == false) { ... this->qcvChart->setRubberBand(QChartView::HorizontalRubberBand); qRubberBand = qcvChart->findChild(); qRubberBand->installEventFilter(this); }`, The corrected code is in: https://github.com/eyllanesc/stackoverflow/tree/master/49538489/psimuvisu – eyllanesc Mar 29 '18 at 12:36
  • @falcon If my answer helps you, do not forget to mark it as correct, if you do not know how to do it, review the [tour], that is the best way to thank. – eyllanesc Mar 29 '18 at 12:41
  • I modified my code but the error: error: no matching function for call to 'MainWindow::rubberBandChanged(QPointF&, QPointF&)' emit this->rubberBandChanged(fp, tp); is not solved and still appears. I done a commit on my bitbucket: https://bitbucket.org/falcon1990/psimuvisu/src/f2734cbab3e2d7dc0d8177836a2af6d770efd6a5?at=master If you want you can check it. Thank you very much ! I'll don't forget to mark it as correct when it will be solved. – falcon Mar 29 '18 at 13:32
  • @falcon is typo in mainwindow.h: `signals: change void rubberBandChanged(QPointF fp, QPoint tp);` to `signals: void rubberBandChanged(QPointF fp, QPointF tp);`, Change the `QPoint` to `QPointF` in the signal declaration. – eyllanesc Mar 29 '18 at 13:57
  • Dammmmmmmmmm I'm sorry for that and the time that you lost for this question. That now works well as I wanted. Thank you so much you are badass ! I will send you a cup of coffe in Peru, just give me an adresse xD. – falcon Mar 29 '18 at 14:11