Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct


    Qt World Summit: Early-Bird Tickets

    Solved Capturing key press in QGraphicsView within main() function?

    General and Desktop
    qgraphicsview qgraphicsscene class main keypressevent
    2
    4
    5304
    Loading More Posts
    • 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.
    • oblivioncth
      oblivioncth last edited by oblivioncth

      Hello,

      I am trying to program a simple game that primarily uses QGraphicsScene and QGraphicsView, both of which are created in the main function of the program (I have no MainWindow). To have the user control the game I simply want them to use the arrow keys. So, I implemented a simple test function to make sure the methodology I researched works:

      void keyPressEvent( QKeyEvent* pe )
      {
          switch( pe->key() )
          {
              case Qt::Key_Space:
              {
              qDebug() << "Space pressed";
              }
              break;
           }
      }
      

      Unfortunately the function is never called. Looking into it some more it seems to me that "keyPressEvent" is a virtual function for widgets that you implement yourself to control its logic. I've seen a good number of examples that discuss this but all are in regards to MainWindow. It seems like I might need to implement a setFocus policy or install an event filter, but I'm not sure how to go about that for my QGraphicsScene since this is not happening within a class (all of the examples I've seen are for capturing key presses within MainWindow.

      If any more code is needed please let me know.

      Thanks again for this great forum.

      EDIT:

      Ok so I read a post on stack overflow that suggested making a custom class that inherits QGraphicsView and then override the keyPressEvent function there. But now I've run into trouble doing that.

      gameview.h:

      #ifndef GAMEVIEW_H
      #define GAMEVIEW_H
      
      #include <QtWidgets>
      
      class GameView : public QGraphicsView
      {
      public:
          GameView();
          void keyPressEvent(QKeyEvent *e);
      };
      
      #endif
      

      gameview.cpp:

      #include "gameview.h"
      
      GameView::GameView()
      {
      
      }
      
      void GameView::keyPressEvent(QKeyEvent *pe)
      {
          switch( pe->key() )
              {
                  case Qt::Key_Space:
                  {
                  qDebug() << "Space pressed";
                  }
                  break;
               }
      }
      

      So now instead of a QGraphicsView I need to create a "GameView", but when I try to instantiate it and hook it to the QGraphicsScene I use:

      QGraphicsScene scene;
      scene.setSceneRect(0, 0, 800, 800);
      scene.setItemIndexMethod(QGraphicsScene::NoIndex);
      
      GameView view(&scene);
      

      I get this error:

      main.cpp:51: error: C2664: 'GameView::GameView(const GameView &)': cannot convert argument 1 from 'QGraphicsScene *' to 'const GameView &'
      

      Clearly something is wrong with binding the Gameview to the GraphicsScene but I'm not sure what. I don't know why its expecting a const GameView reference as a normal GraphicsView has either:

      QGraphicsView(QWidget * parent = 0)
      

      or

      QGraphicsView(QGraphicsScene * scene, QWidget * parent = 0)
      

      as its constructor and just wants a parent, but its probably a flaw in my implementation. I've never had to implement a class that inherits from another in C++/Qt so I'm not totally sure what the right way is.

      It would probably be easier for someone to help with this more specific issue but if you have a better idea for my original question feel free to post anyway.

      1 Reply Last reply Reply Quote 0
      • ?
        A Former User last edited by

        Hi! This is an answer to your original question. You can install an event filter on the QApplication object:

        keypresseventfilter.h

        #ifndef KEYPRESSEVENTFILTER_H
        #define KEYPRESSEVENTFILTER_H
        
        #include <QObject>
        
        class KeyPressEventFilter : public QObject
        {
            Q_OBJECT
        public:
            explicit KeyPressEventFilter(QObject *parent = nullptr);
        
        protected:
            bool eventFilter(QObject *obj, QEvent *event) override;
        };
        
        #endif // KEYPRESSEVENTFILTER_H
        

        keypresseventfilter.cpp

        #include "keypresseventfilter.h"
        
        #include <QKeyEvent>
        #include <QDebug>
        
        KeyPressEventFilter::KeyPressEventFilter(QObject *parent)
            : QObject(parent)
        {
        }
        
        bool KeyPressEventFilter::eventFilter(QObject *obj, QEvent *event)
        {
            if (event->type() != QEvent::KeyPress)
                return QObject::eventFilter(obj, event);
        
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            switch(keyEvent->key()) {
            case Qt::Key_Space: { qDebug() << "Space"; break; }
            case Qt::Key_Left: { qDebug() << "Left"; break; }
            case Qt::Key_Right: { qDebug() << "Right"; break; }
            default: { qDebug() << "Unhandled"; break; }
            }
            return true;
        }
        

        main.cpp

        #include "mainwindow.h"
        #include <QApplication>
        
        #include "keypresseventfilter.h"
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
        
            KeyPressEventFilter *filter = new KeyPressEventFilter(&a);
            a.installEventFilter(filter);
        
            MainWindow w;
            w.show();
        
            return a.exec();
        }
        
        1 Reply Last reply Reply Quote 3
        • ?
          A Former User last edited by

          This is an answer to your modified question.

          customgraphicsview.h

          #ifndef CUSTOMGRAPHICSVIEW_H
          #define CUSTOMGRAPHICSVIEW_H
          
          #include <QGraphicsView>
          #include <QGraphicsScale>
          
          class CustomGraphicsView : public QGraphicsView
          {
              Q_OBJECT
          public:
              explicit CustomGraphicsView(QWidget *parent = nullptr);
              CustomGraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr);
          protected:
              void keyPressEvent(QKeyEvent *event) override;
          };
          
          #endif // CUSTOMGRAPHICSVIEW_H
          

          customgraphicsview.cpp

          #include "customgraphicsview.h"
          
          #include <QKeyEvent>
          
          CustomGraphicsView::CustomGraphicsView(QWidget *parent)
              : QGraphicsView(parent)
          {
          }
          
          CustomGraphicsView::CustomGraphicsView(QGraphicsScene *scene, QWidget *parent)
              : QGraphicsView(scene, parent)
          {
          }
          
          void CustomGraphicsView::keyPressEvent(QKeyEvent *event)
          {
              switch(event->key()) {
              case Qt::Key_Space: { qDebug() << "Space"; break; }
              case Qt::Key_Left: { qDebug() << "Left"; break; }
              case Qt::Key_Right: { qDebug() << "Right"; break; }
              default: { qDebug() << "Unhandled"; break; }
              }
          }
          

          main.cpp

          #include <QApplication>
          
          #include "customgraphicsview.h"
          #include <QGraphicsScene>
          
          int main(int argc, char *argv[])
          {
              QApplication a(argc, argv);
          
              QGraphicsScene scene;
              CustomGraphicsView view(&scene);
              view.show();
          
              return a.exec();
          }
          
          oblivioncth 1 Reply Last reply Reply Quote 3
          • oblivioncth
            oblivioncth @Guest last edited by oblivioncth

            @Wieland Wow you are just killing it today for me aren't you? Haha. I'll judge which is best for me a give it a roll.

            Thanks a bunch (again)!

            EDIT:

            I ended up going for the event filter route and it works beautifully. Other than the exact syntax the approach also feels pretty intuitive which I like.

            1 Reply Last reply Reply Quote 0
            • First post
              Last post