为了账号安全,请及时绑定邮箱和手机立即绑定

如何正确编写PyQT5事件函数

如何正确编写PyQT5事件函数

沧海一幻觉 2023-08-15 17:26:25
如何正确编写事件函数,通过按 Enter 键从一个 QLineEdit 传递到另一个 QLineEdit?我知道如何以这种方式做到这一点:工作示例import sysfrom PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QFormLayoutfrom PyQt5.QtCore import Qt, QEventclass working(QWidget):    def __init__(self):        super().__init__()        self.initUI()    def initUI(self):        self.show()        self.x = QLineEdit(self)        self.x1 = QLineEdit(self)        layout = QFormLayout(self)        layout.addRow("x:", self.x)        layout.addRow("x1:", self.x1)    def event(self, event):        if event.type() == QEvent.KeyPress:            if event.key() in (Qt.Key_Return, Qt.Key_Enter):                self.focusNextPrevChild(True)        return super().event(event)def main():    app = QApplication(sys.argv)    ex = working()    sys.exit(app.exec_())if __name__ == '__main__':    main()现在我想了解如何对这段代码执行相同的操作(我认为问题出在 super() 和init上,但我不知道为什么)。无法工作的基本示例from PyQt5 import QtCore, QtWidgets, QtGui class Ui_MainWindow(object):    def setupUi(self, MainWindow):        MainWindow.setObjectName("MainWindow")        MainWindow.resize(193, 119)        self.centralwidget = QtWidgets.QWidget(MainWindow)        self.centralwidget.setObjectName("centralwidget")        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)        self.verticalLayout_2.setObjectName("verticalLayout_2")         self.x = QtWidgets.QLineEdit()        self.verticalLayout_2.addWidget(self.x)        self.x1 = QtWidgets.QLineEdit()        self.verticalLayout_2.addWidget(self.x1)         MainWindow.setCentralWidget(self.centralwidget)        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", "0")) 
查看完整描述

1 回答

?
杨__羊羊

TA贡献1943条经验 获得超7个赞

第二个示例不起作用,因为您试图重写该event方法,该方法仅适用于 QWidget 子类,而您Ui_MainWindow是一个简单的 pythonobject子类,因此永远不会调用它。


该event()方法由 Qt 在任何 QWidget 上调用,并且由于您在第一个示例中重写了它,因此实际上调用了您的方法。在第二个示例中,您没有重写 QWidget event,但您只是创建了一个永远不会被任何东西调用的函数。


理论上,您可以覆盖对象event的方法(这就是所谓的“猴子修补”):MainWindowsetupUi


    def setupUi(self, MainWindow):

        # ...

        MainWindow.event = self.event

但这是行不通的,因为self您在该函数中引用的实际上是实例Ui_MainWindow,而不是实际的 QMainWindow 实例。虽然您可以使用 lambda,并使用 MainWindow 实例添加参数,但我强烈建议您不要这样做,下面的解释将阐明为什么您不应该这样做。



出于简单的原因,做您想要实现的目标是没有意义的:修改或尝试模仿“pyuic”生成的文件的行为是**永远**不应该做的事情。

不鼓励编辑主要是因为每当您需要从设计器更改 UI 中的某些内容时,您最终都会尝试将新生成的代码(希望您同时没有覆盖该文件)与现有代码集成,这将导致通常会导致大量错误、问题、崩溃和头痛。


不鼓励编辑或模仿,因为这使得实现简单的类操作或覆盖现有方法变得非常困难。另外,虽然我可以理解您有兴趣研究它是如何工作的,但除了阅读如何在 中创建界面之外setupUi,没有什么可以学习的了。pyuic 文件仅用作“实用层”,以简化 PyQt 中的编程,它们应始终仅按照有关使用 Designer 的官方指南中的建议进行导入和使用。


如果您想实现第一个示例的事件,您需要使用您自己的子类并使用上面链接中建议的方法之一。最常见且易于使用的是多重继承方法:


import sys

from PyQt5.QtWidgets import QApplication, QMainWindow, QLineEdit, QFormLayout

from PyQt5.QtCore import Qt, QEvent

from ui_mainwindow import Ui_MainWindow


class Working(QMainWindow, Ui_MainWindow):

    def __init__(self):

        super().__init__()

        self.setupUi(self)


    def event(self, event):

        if event.type() == QEvent.KeyPress:

            if event.key() in (Qt.Key_Return, Qt.Key_Enter):

                self.focusNextPrevChild(True)

        return super().event(event)


if __name__ == "__main__":

    import sys

 

    app = QApplication(sys.argv)

    mainWindow = Working()

    mainWindow.show()

    sys.exit(app.exec_())

注意:我假设您已使用再次生成pyuic了该文件,并且该文件名为ui_mainwindow.py; 另请注意,如果您在设计器中使用 QMainWindow,则必须从同一类(QMainWindow,而不是 QWidget)继承子类;最后,由于您已经从 QMainWindow和Ui_MainWindow 进行子类化,因此您必须创建 的实例Working,而不是 QMainWindow 之一,也不是 Ui_MainWindow 之一。


另一种可能性是使用该uic模块,它允许直接导入.ui文件,而无需每次都重建整个界面。


import sys

from PyQt5.QtWidgets import QApplication, QMainWindow, QLineEdit, QFormLayout

from PyQt5.QtCore import Qt, QEvent

from PyQt5.uic import loadUi


class Working(QMainWindow, Ui_MainWindow):

    def __init__(self):

        super().__init__()

        loadUi('mainWindow.ui', self)

        # ...


查看完整回答
反对 回复 2023-08-15
  • 1 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信