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. Prevent Qt application from reacting to Tab and Alt keys
QtWS25 Last Chance

Prevent Qt application from reacting to Tab and Alt keys

Scheduled Pinned Locked Moved Unsolved General and Desktop
19 Posts 4 Posters 10.2k Views
  • 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.
  • pcsaganP Offline
    pcsaganP Offline
    pcsagan
    wrote on last edited by
    #1

    I'm trying to implement custom behavior in a QGraphicsScene where pressing and releasing the Alt and Tab keys do very specific things related to the scene. However, the keyPressEvent() and keyReleaseEvent() do not fire properly for these keys. I don't know what it's trying to do with Tab, but when I press Alt it seems to set focus to the application's menu bar.

    How do I prevent Qt from reacting to Tab and Alt such that it's no different from pressing the 'P' key (or any other generic key)? I've tried overriding keyPressEvent() and keyReleaseEvent() on every object I could find (including QMainWindow and QApplication), as well as overriding the event() method, but nothing worked.

    Thanks.

    A mosquito was heard to complain, that chemists had poisoned his brain, the cause of his sorrow was paradichlorodiphenyltrichloroethane.

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome
      The tab is special key and used for navigation for various controls.
      I assume override the keyPressEvent() for the graphics view might work but else
      you should look into a eventFilter.

      I would put on the QGraphicsView and see what u get when pressing keys.

      bool eventFilter(QObject *object, QEvent *event) {
      if (event->type() == QEvent::KeyPress) {
      qDebug() << "KeyPress";
      }
      }

      Note that its
      ui->YourGView->installEventfilter(this)
      Where "this" should have the eventFilter function. Often Mainwindow.

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by SGaist
        #3

        Hi and welcome to devnet,

        Do you mean the combo Alt + Tab ? That's a combination usually used by your Window Manager to switch applications so not something to use in your own application. Also Alt is a modifier so it won't trigger a key press event alone.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • pcsaganP Offline
          pcsaganP Offline
          pcsagan
          wrote on last edited by
          #4

          Thanks for the welcomes :)

          Note that I'm using pyqt bindings.

          And no, I did not mean Alt + Tab. I don't know how to describe the behavior I want other than to say I don't want special functionality for the Alt or Tab keys.

          This is what I have tried so far, and it has not prevented the Qt application from performing special behavior (specifically testing by pressing Alt and looking to see if the menu bar stole focus or not):

          class View(QtWidgets.QGraphicsView):
              def __init__(self, scene):
                  super(View, self).__init__(scene)
                  self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
          
              def event(self, event):
                  if event.type() == QtCore.QEvent.KeyPress or event.type() == QtCore.QEvent.KeyRelease:
                      if event.key() == QtCore.Qt.Key_Alt:
                          return True
                  return QtWidgets.QGraphicsView.event(self, event)
          
              def keyPressEvent(self, event):
                  if event.key() == QtCore.Qt.Key_Alt:
                      return
                  QtWidgets.QGraphicsView.keyPressEvent(self, event)
          
              def keyReleaseEvent(self, event):
                  if event.key() == QtCore.Qt.Key_Alt:
                      return
                  QtWidgets.QGraphicsView.keyReleaseEvent(self, event)
          
          class Scene(QtWidgets.QGraphicsScene):
              def __init__(self, *args, **kwargs):
                  super(Scene, self).__init__(*args, **kwargs)
          
              def event(self, event):
                  if event.type() == QtCore.QEvent.KeyPress or event.type() == QtCore.QEvent.KeyRelease:
                      if event.key() == QtCore.Qt.Key_Alt:
                          return True
                  return QtWidgets.QGraphicsScene.event(self, event)
          
              def keyPressEvent(self, event):
                  if event.key() == QtCore.Qt.Key_Alt:
                      return
                  QtWidgets.QGraphicsScene.keyPressEvent(self, event)
          
              def keyReleaseEvent(self, event):
                  if event.key() == QtCore.Qt.Key_Alt:
                      return
                  QtWidgets.QGraphicsScene.keyReleaseEvent(self, event) 
          
          class MainWindow(QtWidgets.QMainWindow):
              def __init__(self):
                  super().__init__()
          
              def event(self, event):
                  if event.type() == QtCore.QEvent.KeyPress or event.type() == QtCore.QEvent.KeyRelease:
                      if event.key() == QtCore.Qt.Key_Alt:
                          return True
                  return QtWidgets.QMainWindow.event(self, event)
          
              def keyPressEvent(self, event):
                  if event.key() == QtCore.Qt.Key_Alt:
                      return
                  QtWidgets.QMainWindow.keyPressEvent(self, event)
          
              def keyReleaseEvent(self, event):
                  if event.key() == QtCore.Qt.Key_Alt:
                      return
                  QtWidgets.QMainWindow.keyReleaseEvent(self, event) 
          
          class Application(QtWidgets.QApplication):
              def __init__(self, args):
                  super().__init__(args)
          
              def event(self, event):
                  if event.type() == QtCore.QEvent.KeyPress or event.type() == QtCore.QEvent.KeyRelease:
                      if event.key() == QtCore.Qt.Key_Alt:
                          return True
                  return QtWidgets.QApplication.event(self, event)
          
              def keyPressEvent(self, event):
                  if event.key() == QtCore.Qt.Key_Alt:
                      return
                  QtWidgets.QApplication.keyPressEvent(self, event)
          
              def keyReleaseEvent(self, event):
                  if event.key() == QtCore.Qt.Key_Alt:
                      return
                  QtWidgets.QApplication.keyReleaseEvent(self, event) 
          

          Overrides for keyPressEvent(), keyReleaseEvent(), and event() methods have no issues for any generic key like 'P' or 'Q' but Alt and Tab are being captured somewhere behind the scenes, and I'm trying to override that special behavior to prevent it from occurring at all.

          A mosquito was heard to complain, that chemists had poisoned his brain, the cause of his sorrow was paradichlorodiphenyltrichloroethane.

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by SGaist
            #5

            Again: Alt is a modifier not a key per se. It won't generate a key press event.
            You will be able to verify it's pressed when there's another "normal" key that is press e.g. "Alt+F" that will open the File menu if there was an accelerator associated with it.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            pcsaganP 1 Reply Last reply
            0
            • SGaistS SGaist

              Again: Alt is a modifier not a key per se. It won't generate a key press event.
              You will be able to verify it's pressed when there's another "normal" key that is press e.g. "Alt+F" that will open the File menu if there was an accelerator associated with it.

              pcsaganP Offline
              pcsaganP Offline
              pcsagan
              wrote on last edited by
              #6

              @SGaist

              I'm not sure what you mean when you say Alt will not generate a key press event. It very much does generate a key press event and a key release event, but they do not happen as one would expect, and I'm guessing it's due to how the focus is changed.

              You can test this by adding an event hook for both key press and key release where they simply print 'Pressed' and 'Released' respectively, and then try pressing Alt. You will see that pressing Alt generates 'Pressed' but releasing does not generate 'Released' and pressing Alt again does not generate the 'Pressed' message again, but releasing it does generate the 'Released' message.

              If you are asserting that the Qt framework makes the assumption that the user never wants to override the behavior of the Alt key, then what you're saying makes sense, but otherwise I don't see why you're asserting that Alt is only a modifier and not a key in and of itself.

              A mosquito was heard to complain, that chemists had poisoned his brain, the cause of his sorrow was paradichlorodiphenyltrichloroethane.

              1 Reply Last reply
              0
              • mrjjM Offline
                mrjjM Offline
                mrjj
                Lifetime Qt Champion
                wrote on last edited by
                #7

                hi
                Its send as a modifier
                void myClass::keyPressEvent(QKeyEvent *e)
                {
                if ((e->key()==Qt::Key_Return) && (e->modifiers()==Qt::AltModifier))
                doSomething();
                }

                So its not really listed as a key.

                pcsaganP 1 Reply Last reply
                0
                • mrjjM mrjj

                  hi
                  Its send as a modifier
                  void myClass::keyPressEvent(QKeyEvent *e)
                  {
                  if ((e->key()==Qt::Key_Return) && (e->modifiers()==Qt::AltModifier))
                  doSomething();
                  }

                  So its not really listed as a key.

                  pcsaganP Offline
                  pcsaganP Offline
                  pcsagan
                  wrote on last edited by
                  #8

                  @mrjj

                  Okay, so is there any way to override that behavior? If not, then it would indeed seem that the Qt framework assumes the user would never want to override the behavior of the Alt key, which is quite odd and unfortunate. In any low level application it's very easy to treat all keys on the keyboard as equal, but of course it's preferable to use Qt over writing custom Windows message pumps.

                  A mosquito was heard to complain, that chemists had poisoned his brain, the cause of his sorrow was paradichlorodiphenyltrichloroethane.

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    What platform are you running your code on ?

                    You made me doubt so I've double checked. On OS X at least, there's indeed key press and release events generated for the modifiers (AFAIK, something new)

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0
                    • pcsaganP Offline
                      pcsaganP Offline
                      pcsagan
                      wrote on last edited by
                      #10

                      :P

                      I'm running on Windows 10 x86-64bit with Python 3.4 and using PyQt5-5.5.1-gpl-Py3.4-Qt5.5.1-x64 bindings.

                      A mosquito was heard to complain, that chemists had poisoned his brain, the cause of his sorrow was paradichlorodiphenyltrichloroethane.

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Can you check with a basic C++ project if you have the same results ? Just to be sure PyQt is innocent.

                        #include <QApplication>
                        #include <QWidget>
                        #include <QtDebug>
                        
                        class MyWidget : public QWidget
                        {
                        public:
                            explicit MyWidget(QWidget *parent = nullptr)
                                : QWidget(parent)
                            {}
                        
                            void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE
                            {
                                qDebug() << "Pressed" << (Qt::Key) event->key();
                            }
                        
                            void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE
                            {
                                qDebug() << "Released" << (Qt::Key) event->key();
                            }
                        
                        };
                        
                        int main(int argc, char *argv[])
                        {
                            QApplication app(argc, argv);
                            MyWidget mw;
                            mw.show();
                            return app.exec();
                        }
                        

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        kshegunovK 1 Reply Last reply
                        1
                        • mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on last edited by mrjj
                          #12

                          hi
                          Test on win 10, Qt 5.5, empty mainwindow

                          void keyReleaseEvent(QKeyEvent* e) {
                          qDebug() << "release" << (e->key() == Qt::Key_Alt);
                          if ( e->modifiers() == Qt::AltModifier)
                          qDebug() << "ALT up";
                          }

                          void keyPressEvent(QKeyEvent* e) {
                          if ( e->modifiers() == Qt::AltModifier)
                          qDebug() << "ALT down" << (e->key() == Qt::Key_Alt);
                          }

                          Give me "ALT up/down" with key Qt::Key_Alt.
                          So seem it does send it also as key. (on windows)

                          UPDATE:
                          It gives me ALT as modifier on down , but only as key when released. ( make sense)

                          1 Reply Last reply
                          2
                          • SGaistS SGaist

                            Can you check with a basic C++ project if you have the same results ? Just to be sure PyQt is innocent.

                            #include <QApplication>
                            #include <QWidget>
                            #include <QtDebug>
                            
                            class MyWidget : public QWidget
                            {
                            public:
                                explicit MyWidget(QWidget *parent = nullptr)
                                    : QWidget(parent)
                                {}
                            
                                void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE
                                {
                                    qDebug() << "Pressed" << (Qt::Key) event->key();
                                }
                            
                                void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE
                                {
                                    qDebug() << "Released" << (Qt::Key) event->key();
                                }
                            
                            };
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication app(argc, argv);
                                MyWidget mw;
                                mw.show();
                                return app.exec();
                            }
                            
                            kshegunovK Offline
                            kshegunovK Offline
                            kshegunov
                            Moderators
                            wrote on last edited by kshegunov
                            #13

                            @SGaist
                            The key events are also available on Linux (Debian, 4.x kernel with Qt 5.5).
                            I always thought that modifiers are sent only as such, not as regular keys, but I guess this had been changed at some point ...

                            @pcsagan,
                            Seeing that @mrjj also receives presses/releases correctly, I'd guess there's something specific to the python bindings, but you should run the example code to make sure.

                            Read and abide by the Qt Code of Conduct

                            1 Reply Last reply
                            0
                            • pcsaganP Offline
                              pcsaganP Offline
                              pcsagan
                              wrote on last edited by
                              #14

                              Hey guys, I ran this test as requested and it works the way the C++ implementation works, and which also happens to be the functionality I desired.

                              from PyQt5 import QtCore, QtWidgets
                              import sys
                              
                              class Widget(QtWidgets.QWidget):
                                  def __init__(self, parent=None):
                                      super(Widget, self).__init__(parent)
                              
                                  def keyPressEvent(self, event):
                                      if event.key() == QtCore.Qt.Key_Alt:
                                          print('Alt pressed!')
                              
                                  def keyReleaseEvent(self, event):
                                      if event.key() == QtCore.Qt.Key_Alt:
                                          print('Alt released!')
                              
                              if __name__ == '__main__':
                                  app = QtWidgets.QApplication(sys.argv)
                                  widget = Widget()
                                  widget.show()
                                  sys.exit(app.exec_())
                              

                              What's interesting is that this behavior changes when you create a menu in the menubar via:

                              self.fileMenu = self.menuBar().addMenu('&File')
                              self.newConsoleAct = QtWidgets.QAction(QtGui.QIcon('assets/icons/console.png'), '&New Console', self, shortcut='Ctrl+N', statusTip='Create a new client console', triggered=self.newConsole)
                              self.fileMenu.addAction(self.newConsoleAct)
                              

                              The code above will capture the focus and set it to the menu bar, and I don't know how to prevent this from happening. What's even more interesting is that when you add a QtWidgets.QMdiArea the behavior changes to what I originally described where the 'in between' key press/release events are somehow consumed, and you need to press and release Alt twice to see both pressed and release events trigger, and it still sets focus to the menu bar.

                              I assume that if you guys were to create a test application that had a menu bar and MDI area you'd see the same change in behavior of the keyPressEvent() and keyReleaseEvent(). I'm hoping I eventually discover some kind of policy flag that disables this behavior, but in the mean time I think I'll just use non-modifier keys for my scene's custom controls. I appreciate the help from you guys regardless. Thanks!

                              A mosquito was heard to complain, that chemists had poisoned his brain, the cause of his sorrow was paradichlorodiphenyltrichloroethane.

                              1 Reply Last reply
                              0
                              • SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                &File < there you have an accelerator thus the the Key_Alt + Key_F combo must be detected.
                                Same goes for newConsoleAct where you have both an accelerator and a shortcut which must also be detected.

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                pcsaganP 1 Reply Last reply
                                0
                                • SGaistS SGaist

                                  &File < there you have an accelerator thus the the Key_Alt + Key_F combo must be detected.
                                  Same goes for newConsoleAct where you have both an accelerator and a shortcut which must also be detected.

                                  pcsaganP Offline
                                  pcsaganP Offline
                                  pcsagan
                                  wrote on last edited by
                                  #16

                                  @SGaist

                                  Yeah, that's the functionality I'm trying to disable.

                                  A mosquito was heard to complain, that chemists had poisoned his brain, the cause of his sorrow was paradichlorodiphenyltrichloroethane.

                                  1 Reply Last reply
                                  0
                                  • SGaistS Offline
                                    SGaistS Offline
                                    SGaist
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #17

                                    If you want to disable that, why not avoid accelerators ?

                                    Interested in AI ? www.idiap.ch
                                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                    1 Reply Last reply
                                    0
                                    • pcsaganP Offline
                                      pcsaganP Offline
                                      pcsagan
                                      wrote on last edited by
                                      #18

                                      The thing is I actually really like the default behavior of the Qt framework, and it's remarkable at providing easy access to convenient and common functionality straight out of the box. I don't want to avoid accelerators because I want to provide keyboard shortcuts for the various things users can do in my application.

                                      I was hoping that in my QGraphicsScene I could have the Ctrl key toggle between ScrollHandDrag and RubberBandDrag drag modes while still retaining Ctrl+<Key> shortcut functionality in the application (I simply wasn't going to assign the Alt key to any accelerators). I also wanted to toggle displaying textual information above items in the scene while the user has Alt pressed down (like Diablo 2 when items are on the ground, you only see the item text while Alt is held in a pressed state).

                                      So in my application with a menu bar, MDI central widget, and graphics scene MDI child window, I effectively want to be able to press Ctrl + drag the mouse to select many items, then hold Alt to verify they're the ones I wanted selected by reading the text above them, then press Ctrl+R to rotate all selected items by 90 degrees.

                                      When I said "that's the functionality I want to disable" I was referring to the mechanism that automatically captures the Alt key and reacts to it. I want to be in complete control of how the application responds to the Alt key. To be fair, and as I stated earlier, I can just use 'Q' and 'A' and 'Z' to achieve the functionality I want, but it's less intuitive than using the modifier keys to change the behavior of the scene (i.e. change selection mode and display item text).

                                      A mosquito was heard to complain, that chemists had poisoned his brain, the cause of his sorrow was paradichlorodiphenyltrichloroethane.

                                      kshegunovK 1 Reply Last reply
                                      0
                                      • pcsaganP pcsagan

                                        The thing is I actually really like the default behavior of the Qt framework, and it's remarkable at providing easy access to convenient and common functionality straight out of the box. I don't want to avoid accelerators because I want to provide keyboard shortcuts for the various things users can do in my application.

                                        I was hoping that in my QGraphicsScene I could have the Ctrl key toggle between ScrollHandDrag and RubberBandDrag drag modes while still retaining Ctrl+<Key> shortcut functionality in the application (I simply wasn't going to assign the Alt key to any accelerators). I also wanted to toggle displaying textual information above items in the scene while the user has Alt pressed down (like Diablo 2 when items are on the ground, you only see the item text while Alt is held in a pressed state).

                                        So in my application with a menu bar, MDI central widget, and graphics scene MDI child window, I effectively want to be able to press Ctrl + drag the mouse to select many items, then hold Alt to verify they're the ones I wanted selected by reading the text above them, then press Ctrl+R to rotate all selected items by 90 degrees.

                                        When I said "that's the functionality I want to disable" I was referring to the mechanism that automatically captures the Alt key and reacts to it. I want to be in complete control of how the application responds to the Alt key. To be fair, and as I stated earlier, I can just use 'Q' and 'A' and 'Z' to achieve the functionality I want, but it's less intuitive than using the modifier keys to change the behavior of the scene (i.e. change selection mode and display item text).

                                        kshegunovK Offline
                                        kshegunovK Offline
                                        kshegunov
                                        Moderators
                                        wrote on last edited by kshegunov
                                        #19

                                        @pcsagan
                                        Maybe you could use void qt_set_sequence_auto_mnemonic(bool enable) to disable the menu bar from intercepting the alt key presses?

                                        PS. I forgot you were working with python. I don't know a way to call that function from pyton as it most probably is not available in the bindings ...

                                        Read and abide by the Qt Code of Conduct

                                        1 Reply Last reply
                                        0

                                        • Login

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