简体   繁体   English

keyPressEvent 不适用于 PyQt5 中的 Enter 键(但适用于所有其他键)

[英]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.我有一个 PyQt5 GUI,它有一个主要的 window,里面有按钮和 QLineEdit。

I made the keyPressEvent function and set certain keys on the keyboard to do different things.我制作了 keyPressEvent function 并在键盘上设置了某些键来做不同的事情。 All of the keys that I set work other than the Enter button.我设置的所有键都可以使用,而不是 Enter 按钮。 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.当您按下 Enter 键时,如果未单击屏幕按钮,则会触发数字 7 屏幕按钮(这是 GUI 中制作的第一个按钮)。 Once a pushbutton is clicked then the Enter key will always trigger the last onscreen pushbutton that was clicked.单击按钮后,Enter 键将始终触发最后一次单击的屏幕按钮。 All the other events work fine.所有其他事件工作正常。 Anyone know why this is happening?有谁知道为什么会这样?

MRE: 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. Equal 键工作正常,Enter 键不行。

The problem is that the Enter key is associated with Qt.Key_Return, and only in keypads is it Qt.Key_Enter.问题是Enter键与 Qt.Key_Return 相关联,并且仅在键盘中是 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.但是,它并不能纠正真正的错误,因为问题在于按钮具有焦点,因此 keypress 事件不会传播到其父级。

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.此外,不建议执行foo.keyPressEvent = bar ,因为在许多情况下它可能会失败,如果您有“n”个小部件,则必须为所有小部件实现该逻辑。 A more elegant solution is to use an event filter on the window.更优雅的解决方案是在 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所以你必须恢复 .py 文件,因为不建议修改它(参见这篇文章: QtDesigner changes will be lost after redesign User Interface ),我假设它被称为 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_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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