简体   繁体   中英

Ctrl+Alt key modifier behavior with Qt on windows when a textbox has focus

I made a quick sample program to demonstrate the problem

import sys

from  PyQt4 import QtGui
from PyQt4.QtCore import Qt

class AWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(AWindow, self).__init__(parent=parent)

        self.setCentralWidget(QtGui.QWidget())
        self.centralWidget().setLayout(QtGui.QFormLayout())

        self.centralWidget().layout().addRow(
            QtGui.QLabel('some text'),
            QtGui.QLineEdit()
            )
        self.centralWidget().layout().addRow(
            QtGui.QLabel('some text'),
            QtGui.QCheckBox('this is checkbox')            
            )

    def keyPressEvent(self, e):
        if int(e.modifiers()) == (Qt.ControlModifier+Qt.AltModifier):
            if e.key() == Qt.Key_K:
                #when ctrl+alt+k is pressed, a message box should open
                msg = QtGui.QMessageBox(
                    QtGui.QMessageBox.Information,
                    'w00t',
                    'You pressed ctrl+alt+k'
                    )
            msg.exec_()
def main():
    app = QtGui.QApplication(sys.argv)
    w = AWindow()
    w.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

The problem

In this sample I'm capturing the ctrl+alt+k keyboard shortcut. The problem is that if a text entry widget has keyboard focused when those keys are pressed, it is not captured by the keyPressEevent handler, instead an upper case K is typed into the box. (this is the same with all ctrl+alt keypresses).

If another kind of widget is focused, one that does not accept text input (eg a checkbox, button) the key press is registered as it should and in the sample, the messagebox is shown.
Also, keyboard shortcuts that use only a Ctrl modifier work fine.

This problem only presents it self on Windows, but not on Linux, so this leads me to believe this has something to do with how windows handles the ctrl+alt modifier, or perhaps I'm not capturing the modifiers properly.

Is there any way to fix this?

Edit

I derived this solution from Spidey's comment.
I sublassed the QLineEdit and handled it's keyPressEvent like this.

#EDIT: this doesn't work, see below
def keyPressEvent(self, e):
    if e.modifiers() and Qt.ControlModifier and Qt.AltModifier:
        e.ignore()
    super(CoolLineEdit, self).keyPressEvent(e)

Edit again

Adding up the modifiers as ints and returning after e.ignore() (maybe ignore isn't needed) seems to be very important.
This is the real fix.

def keyPressEvent(self, e):
    if int(e.modifiers()) == (QtCore.Qt.ControlModifier+QtCore.Qt.AltModifier):
        e.ignore()
        return
    super(SaveLineEdit, self).keyPressEvent(e)            

The QLineEdit , when it has focus, is handling the `QKeyEvent . If you need this functionality on Windows, I would suggest:

1) Derive a class from QLineEdit (or whatever QTextEdit -derived class you want).

2) Override virtual void keyPressEvent(QKeyEvent* e) and check for your specific key-combo.

3) If you find it, return without handling it, and it will fall to the next level (your window, which will catch it and print your message).

4) If you don't find it, explicitly call the base-class version of the function: BaseClass::keyPressEvent(e); so that normal key presses are handled correctly.

Sorry for c++ syntax, I haven't used PyQt.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM