简体   繁体   中英

keyPressEvent not working for Enter key in PyQt5 (but works for every other key)

I have a PyQt5 GUI which has a main window with buttons and a QLineEdit in it.

I made the keyPressEvent function and set certain keys on the keyboard to do different things. All of the keys that I set work other than the Enter button. When you press the Enter key it either triggers the number 7 onscreen pushbutton (which is the first button made in the GUI) if no onscreen pushbutton was clicked. Once a pushbutton is clicked then the Enter key will always trigger the last onscreen pushbutton that was clicked. All the other events work fine. Anyone know why this is happening?

MRE:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QDialog, QPushButton
from PyQt5.QtCore import*
from PyQt5.QtWidgets import*

if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'):
    QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
if hasattr(QtCore.Qt, 'AA_UseHighDpiPixmaps'):
    QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
    
# I know global variables is bad programming. Just doing this for the example
outputText = ""

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        
        MainWindow.setFixedSize(331, 411)
       
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.button_7 = QtWidgets.QPushButton(self.centralwidget)
        self.button_7.setGeometry(QtCore.QRect(20, 190, 71, 41))
        self.button_7.setStyleSheet("QPushButton\n"
"{\n"
"border: none;\n"
"background-color: rgb(255, 255, 255);\n"
"font: 20pt \"Arial\";\n"
"}\n"
"QPushButton:hover{\n"
"background-color: rgb(220, 220, 220);\n"
"}\n"
"QPushButton:pressed\n"
"{\n"
"background-color: rgb(212, 212, 212);\n"
"}\n"
"\n"
"")
        self.button_7.setAutoDefault(True)
        self.button_7.setDefault(False)
        self.button_7.setFlat(True)
        self.button_7.setObjectName("button_7")
        self.button_7.clicked.connect(self.click_and_update)

        self.screenOutput = QtWidgets.QLineEdit(self.centralwidget)
        self.screenOutput.setGeometry(QtCore.QRect(20, 30, 291, 20))
        self.screenOutput.setStyleSheet("border: none; background: transparent;"
        "font: 12pt \"MS Shell Dlg 2\";\n""color: rgb(190, 190, 190);")
        self.screenOutput.setAlignment(QtCore.Qt.AlignCenter)
        self.screenOutput.setObjectName("eqInput")
        

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 331, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", " MRE"))
        self.button_7.setText(_translate("MainWindow", "7"))
        self.screenOutput.setText(_translate("MainWindow", "Do Something"))

        # set keyPressEvent to current widgets that we'd like it to be overridden
        self.centralwidget.keyPressEvent = self.keyPressEvent
        self.screenOutput.keyPressEvent = self.keyPressEvent
   
    def keyPressEvent(self,e):
        if e.key() == Qt.Key_Enter:
                self.equal_click()

        if e.key() == Qt.Key_Equal:
                self.equal_click()
   

    def update_screen(self):
        self.screenOutput.setText(outputText)
        return


    def equal_click(self):
        global outputText
        outputText = "Pressed Key"
        self.update_screen()
        return

    def click_and_update(self):
        global outputText
        outputText+=" 7"
        self.update_screen()
        return

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

The Equal key works fine, the Enter key does not.

The problem is that the Enter key is associated with Qt.Key_Return, and only in keypads is it Qt.Key_Enter. So a generic solution is to check both keys:

if e.key() in (Qt.Key_Return, Qt.Key_Enter):
    self.equal_click()

However, it does not correct the real error since the problem is that the button has focus, so the keypress event is not propagated to its parent.

Also it is not advisable to do foo.keyPressEvent = bar since in many cases it can fail and if you have "n" widgets you will have to implement that logic for all of them. A more elegant solution is to use an event filter on the window. So you must restore the.py file since it is not recommended to modify it (see this post: QtDesigner changes will be lost after redesign User Interface ) and I will assume that it is called main_ui.py

from PyQt5 import QtCore, QtWidgets

from main_ui import Ui_MainWindow


class KeyHelper(QtCore.QObject):
    keyPressed = QtCore.pyqtSignal(QtCore.Qt.Key)

    def __init__(self, window):
        super().__init__(window)
        self._window = window

        self.window.installEventFilter(self)

    @property
    def window(self):
        return self._window

    def eventFilter(self, obj, event):
        if obj is self.window and event.type() == QtCore.QEvent.KeyPress:
            self.keyPressed.emit(event.key())
        return super().eventFilter(obj, event)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

    def handle_key_pressed(self, key):
        if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
            self.update_text()

    def update_text(self):
        text = self.ui.screenOutput.text() + "7"
        self.ui.screenOutput.setText(text)


if hasattr(QtCore.Qt, "AA_EnableHighDpiScaling"):
    QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
if hasattr(QtCore.Qt, "AA_UseHighDpiPixmaps"):
    QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()
    w.show()

    helper = KeyHelper(w.windowHandle())
    helper.keyPressed.connect(w.handle_key_pressed)

    sys.exit(app.exec_())

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