Struggling with mouse events
-
I am trying to catch both keyboard and mouse events. I am able to get both KeyPress and KeyRelease events, but I'm only able to get MouseButtonPress events. Something is eating the MouseButtonRelease events before I can see them.
Below is a very stripped down app that shows the problem. I'm using QtCreator and I simply added a QGraphicsView, to which I attach the eventFilter.
Interestingly, in the code below, if I comment out the
ui->graphicsView->setScene(m_scene);
line then I don't even get the MouseButtonPress events, but I still get the KeyPress and KeyRelease events.One last comment - if I change the
else
clause of the eventFilter to always returntrue
instead ofQObject::eventFilter(obj, event);
then I do get both MouseButtonPress and MouseButtonRelease events, but the graphicsView doesn't work properly, because it is not getting its events.#include "map.h" #include "./ui_map.h" Map::Map(QWidget *parent) : QMainWindow(parent), ui(new Ui::Map) { ui->setupUi(this); m_scene = new QGraphicsScene(); ui->graphicsView->setScene(m_scene); ui->graphicsView->installEventFilter(this); } Map::~Map() { delete ui; } bool Map::eventFilter(QObject *obj, QEvent *event) { qInfo() << "event " << event; if(event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); qDebug("Ate key press %d", keyEvent->key()); return true; } else if(event->type() == QEvent::KeyRelease) { QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); qDebug("Ate key release %d", keyEvent->key()); return true; } else if(event->type() == QEvent::MouseButtonPress) { QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); qDebug("Ate mouse press %d", mouseEvent->button()); return true; } else if(event->type() == QEvent::MouseButtonRelease) { QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); qDebug("Ate mouse release %d", mouseEvent->button()); return true; } else { // standard event processing return QObject::eventFilter(obj, event); } }
For completeness, here is the header file:
#ifndef MAP_H #define MAP_H #include <QMainWindow> #include <QKeyEvent> #include <QMouseEvent> #include <QGraphicsScene> #include <QGraphicsView> QT_BEGIN_NAMESPACE namespace Ui { class Map; } QT_END_NAMESPACE class Map : public QMainWindow { Q_OBJECT public: explicit Map(QWidget *parent = nullptr); ~Map(); private: Ui::Map *ui; QGraphicsScene* m_scene; bool eventFilter(QObject *obj, QEvent *event); }; #endif // MAP_H
And here is the ui file:
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Map</class> <widget class="QMainWindow" name="Map"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>425</width> <height>824</height> </rect> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="sizeIncrement"> <size> <width>0</width> <height>0</height> </size> </property> <property name="baseSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="windowTitle"> <string>Map</string> </property> <widget class="QWidget" name="centralwidget"> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="QGraphicsView" name="graphicsView"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="alignment"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> </property> </widget> </item> </layout> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>425</width> <height>23</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui>
-
QGraphicsView
doesn't like to propagate mouseEvents (I know there is something but cant remember the correct explanation right now).
The better solution is to re-implement themousePressEvent
andmouseReleaseEvent
in aQGraphicsView
subclass directly.Edit:
Btw, if you still want to stick to your solution, install the filter on the
QGraphicsScene
(not view), and catch like this:if(event->type() == QGraphicsSceneMouseEvent::GraphicsSceneMouseRelease) { QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event); qDebug("Ate Graphics mouse release %d", mouseEvent->button()); return false; // or true, if you want to swallow the event here. // but this might cause unwanted behavior within the view/scene } if(event->type() == QGraphicsSceneMouseEvent::GraphicsSceneMousePress) { QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event); qDebug("Ate Graphics mouse press %d", mouseEvent->button()); return false; // same here }
(Note the
QGraphicsSceneMouseEvent
-type)The normal key event will also still work :)
-
@Pl45m4 said in Struggling with mouse events:
QGraphicsView subclass
Installing the filter on the scene works perfectly. Thanks!
-