Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Struggling with mouse events
Forum Updated to NodeBB v4.3 + New Features

Struggling with mouse events

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 605 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SteveFalco
    wrote on last edited by
    #1

    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 return true instead of QObject::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>
    
    Pl45m4P 1 Reply Last reply
    0
    • S SteveFalco

      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 return true instead of QObject::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>
      
      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by Pl45m4
      #2

      @SteveFalco

      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 the mousePressEvent and mouseReleaseEvent in a QGraphicsView 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 :)


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      S 1 Reply Last reply
      1
      • Pl45m4P Pl45m4

        @SteveFalco

        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 the mousePressEvent and mouseReleaseEvent in a QGraphicsView 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 :)

        S Offline
        S Offline
        SteveFalco
        wrote on last edited by
        #3

        @Pl45m4 said in Struggling with mouse events:

        QGraphicsView subclass

        Installing the filter on the scene works perfectly. Thanks!

        1 Reply Last reply
        0
        • S SteveFalco has marked this topic as solved on

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved