I am pretty new to Qt and C++. I have a component which inherits QChartView. In this component I want to override the "mouseMove" event from QChartView and I also want to connect the recieved "hovered" signal from QScatterSeries to a slot in the same class. A simplified version of my code which can be reproduced is given below (written in Qt6.5):
interactive_chart.h
#ifndef INTERACTIVECHARTVIEW_H
#define INTERACTIVECHARTVIEW_H
#include <QtCharts/QChartView>
#include <QDebug>
#include <QToolTip>
#include <QCursor>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QValueAxis>
#include <QPainter>
#include <QTimer>
#include <QCursor>
namespace Common::ScatterChartGroup
{
class InteractiveChartView : public QChartView
{
private:
const int panningStep = 10;
// these panning values are used to store the user panning input for reset purpose.
QChart *chart;
QValueAxis *axisX;
QValueAxis *axisY;
QTimer timer;
QScatterSeries *series;
void onMouseMoveStop();
void drawChart(QValueAxis *x_axis, QValueAxis *y_axis);
void mouseMoveEvent(QMouseEvent *event);
InteractiveChartView(QChart *chart);
public:
static InteractiveChartView* getInstance();
public slots:
void onMouseHovered(const QPointF &point, bool state);
};
}
#endif // INTERACTIVECHARTVIEW_H
interactiveChart.cpp
#include "interactive_chart_view.h"
InteractiveChartView::InteractiveChartView(QChart *chart): QChartView (chart)
{
this->chart = chart;
chart->setAcceptHoverEvents(true);
chart->legend()->hide();
axisX = new QValueAxis;
axisY = new QValueAxis;
chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(axisY, Qt::AlignLeft);
drawChart(axisX,axisY);
//The following is to detect when mouse stops moving
setMouseTracking(true);
timer.setInterval(250);
timer.setSingleShot(true);
this->connect(this->series, &QScatterSeries::hovered, this,
&InteractiveChartView::onMouseHovered);
this->connect(&timer,&QTimer::timeout,this, &InteractiveChartView::onMouseMoveStop);
}
InteractiveChartView* InteractiveChartView::getInstance()
{
QChart *chart = new QChart();
InteractiveChartView *interactiveChartView = new InteractiveChartView(chart);
return interactiveChartView;
}
void InteractiveChartView::onMouseHovered(const QPointF &point, bool state)
{
QString tooltipText = "x: " + QString::number(point.x()) + "\ny: " + QString::number(point.y());
if(state)
{
QToolTip::showText(QCursor::pos(),tooltipText ,nullptr);
}else
{
QToolTip::hideText();
}
}
void InteractiveChartView::onMouseMoveStop()
{
qDebug() << "Mouse Stopped";
}
void InteractiveChartView::drawEmptyChart(QValueAxis *xAxis, QValueAxis *yAxis)
{
series->attachAxis(xAxis);
series->attachAxis(yAxis);
axisX->setRange(0,10);
axisY->setRange(0,10);
QRandomGenerator randGenerator; // This is a temporary random data generator for testing
for (int i = 0;i<=10;i++) {
series.append(QPointF(randGenerator.bounded(20.0),randGenerator.bounded(20.0)));
}
}
void InteractiveChartView::mouseMoveEvent(QMouseEvent *event)
{
timer.start();
}
As can be seen I used the QScatterSeries "hovered" signal to show tooltip and used "mouseMove" event to detect when the mouse stops moving. The problem is the "mouseMove" event prevents the "hovered" signal to be triggered (or recieved?). The tooltip stops showing up when I started using "mouseMove" event. There seems to be some kind of collision between these two events.
To make it brief, I tried using the "hovered" signal from QScatterSeries and "mouseMove" event from QChartView in the same component and expected both to function normally. But "mouseMove" event prevents the slot connected to "hovered" signal to be executed. Once I remove the mouse move event from the code, everything works fine. What is your suggestion? I appreciate the help.
The parent classes mouseMoveEvent
handler will be responsible for generating the hover
signal. You should call the parent class handler when overriding event handlers unless you want to stop any further event processing:
void InteractiveChartView::mouseMoveEvent(QMouseEvent *event)
{
timer.start();
QChartView::mouseMoveEvent(event);
}