如何正确编写 PyQT5 事件函数
Posted
技术标签:
【中文标题】如何正确编写 PyQT5 事件函数【英文标题】:How to write correctly PyQT5 event function 【发布时间】:2020-09-17 16:51:10 【问题描述】:如何正确编写事件函数,通过按回车键从一个 QLineEdit 传递到另一个 QLineEdit?
我知道该怎么做:
工作示例
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QFormLayout
from PyQt5.QtCore import Qt, QEvent
class 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 但我不知道为什么)。
UNWorking 基本示例
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"))
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 = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
【问题讨论】:
你为什么要用“那个”代码来做这个?是不是因为您想使用 Designer 构建应用程序而不是手动创建整个界面? 主要用于学习,在第二个逻辑中,我可以在不关闭整个应用程序的情况下执行 MainWindow.Close()。我是初学者,我不明白如何正确使用 init super() 和 parent 【参考方案1】:第二个示例不起作用,因为您试图覆盖 event
方法,该方法仅适用于 QWidget 子类,而您的 Ui_MainWindow
是一个简单的 python object
子类,所以它永远不会被调用。
event()
方法由 Qt 在任何 QWidget 上调用,并且由于您在第一个示例中覆盖了它,因此实际上调用了您的方法。在第二个示例中,您没有覆盖 QWidget event
,而只是创建了一个永远不会被任何东西调用的函数。
理论上你可以覆盖setupUi
中MainWindow
对象的event
方法(这就是所谓的“猴子补丁”):
def setupUi(self, MainWindow):
# ...
MainWindow.event = self.event
但这不起作用,因为您在该函数中所指的 self
实际上是 Ui_MainWindow
实例,而不是实际的 QMainWindow 实例。虽然您可以使用 lambda,并在 MainWindow 实例中添加参数,但我强烈建议您不要这样做,以下解释将阐明您为什么不应该这样做。
不鼓励编辑主要是因为当您需要从 Designer 更改 UI 中的某些内容时,您最终会尝试将新生成的代码(希望您同时没有覆盖文件)与现有代码集成,这通常会导致大量错误、问题、崩溃和令人头疼的问题。
不鼓励编辑或模仿,因为它很难实现简单的类操作或覆盖现有方法。此外,虽然我可以理解您有兴趣研究它是如何工作的,但除了阅读如何在 setupUi
中创建界面之外,没有什么要学习的了。 pyuic 文件仅用作“实用层”以简化 PyQt 中的编程,它们应该始终仅按照有关 using 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)
# ...
【讨论】:
我在 pastebin 中放了一个新的例子 @yalodek(请用英文写) 什么不起作用?你检查过字母大小写吗?如果Ui_MainWindow
在同一个文件中,那么您不应该导入它(但您应该不将该类放在脚本中,因为应该始终导入 pyuic 文件)。
查看我的编辑。你应该只创建一个Working
的实例,而不是 QMainWindow 和 Working。
现在它工作得很好,我没有看到现在我需要用 mainWindow 调用它。谢谢
不客气。请记住,如果我的回答按预期解决了您的问题,您应该通过单击左侧的复选标记将其标记为已接受。以上是关于如何正确编写 PyQT5 事件函数的主要内容,如果未能解决你的问题,请参考以下文章