带有自定义插槽的PyQt5设计器



我仍在试图弄清楚PyQt,但遇到了另一个问题,我在过去几个小时里一直在思考这个问题。当我使用pyuic5将.ui文件转换为.py文件时,输出的一部分(在类ui_MainWindow中(将信号连接到插槽:

self.browseButton.clicked.connect(MainWindow.browseSlot)
self.importButton.clicked.connect(MainWindow.importSlot)
self.lineEdit.returnPressed.connect(MainWindow.returnPressedSlot)

这是从主要功能调用的:

def main():
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = MainWindowUI()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

以上,在同一个文件中,我有以下代码:

class MainWindowUI(Ui_MainWindow):
def __init__(self):
super().__init__()
self.model = Model()
def setupUi(self, mainWindow):
super().setupUi(mainWindow)
def debugPrint(self, msg):
self.textEdit.append(msg)
def refreshAll(self):
self.lineEdit.setText(self.model.getFileName())
self.textEdit.setText(self.model.getFileContents())
def returnPressedSlot(self):
self.debugPrint('Return key pressed')
def importSlot(self):
self.debugPrint('Import button pressed')
def browseSlot(self):
self.debugPrint('Browse button pressed')

我得到的确切错误是:

AttributeError: 'QMainWindow' object has no attribute 'browseSlot'

这实际上非常合理,因为QtWidgets.QMainWindow()没有理由知道我在MainWindowUI类中定义的自定义插槽。因此,它不起作用是有道理的,但我对我应该做什么不同感到困惑。这就是我看过的每一个教程的设置方式,所以很明显,我在某个地方有一个根本的误解。如有任何帮助澄清此问题,我们将不胜感激!

非常感谢。


编辑以添加我的Ui_MainWindow类的完整代码:

# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'test.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(798, 593)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.verticalLayout = QtWidgets.QVBoxLayout(self.tab)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.frame_2 = QtWidgets.QFrame(self.tab)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.debugTextBrowser = QtWidgets.QTextBrowser(self.frame_2)
self.debugTextBrowser.setGeometry(QtCore.QRect(10, 10, 351, 461))
self.debugTextBrowser.setObjectName("debugTextBrowser")
self.horizontalLayout_2.addWidget(self.frame_2)
self.frame = QtWidgets.QFrame(self.tab)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.browseButton = QtWidgets.QPushButton(self.frame)
self.browseButton.setGeometry(QtCore.QRect(80, 30, 51, 20))
self.browseButton.setObjectName("browseButton")
self.lineEdit = QtWidgets.QLineEdit(self.frame)
self.lineEdit.setGeometry(QtCore.QRect(80, 10, 281, 20))
self.lineEdit.setObjectName("lineEdit")
self.importButton = QtWidgets.QPushButton(self.frame)
self.importButton.setGeometry(QtCore.QRect(310, 30, 51, 20))
self.importButton.setObjectName("importButton")
self.textEdit = QtWidgets.QTextEdit(self.frame)
self.textEdit.setGeometry(QtCore.QRect(80, 130, 281, 81))
self.textEdit.setObjectName("textEdit")
self.horizontalLayout_2.addWidget(self.frame)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.setupProgressBar = QtWidgets.QProgressBar(self.tab)
self.setupProgressBar.setProperty("value", 0)
self.setupProgressBar.setTextVisible(False)
self.setupProgressBar.setInvertedAppearance(False)
self.setupProgressBar.setTextDirection(QtWidgets.QProgressBar.TopToBottom)
self.setupProgressBar.setObjectName("setupProgressBar")
self.verticalLayout.addWidget(self.setupProgressBar)
self.tabWidget.addTab(self.tab, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.tabWidget.addTab(self.tab_2, "")
self.tab_3 = QtWidgets.QWidget()
self.tab_3.setObjectName("tab_3")
self.tabWidget.addTab(self.tab_3, "")
self.tab_4 = QtWidgets.QWidget()
self.tab_4.setObjectName("tab_4")
self.tabWidget.addTab(self.tab_4, "")
self.tab_5 = QtWidgets.QWidget()
self.tab_5.setObjectName("tab_5")
self.tabWidget.addTab(self.tab_5, "")
self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 798, 18))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(0)
self.browseButton.clicked.connect(MainWindow.browseSlot)
self.importButton.clicked.connect(MainWindow.importSlot)
self.lineEdit.returnPressed.connect(MainWindow.returnPressedSlot)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.browseButton.setText(_translate("MainWindow", "Browse"))
self.importButton.setText(_translate("MainWindow", "Import"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Setup"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Production Forecast"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Production Forecast"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("MainWindow", "Page"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_5), _translate("MainWindow", "Page"))

PyQt在您的文档中建议您应该从适当的小部件继承,在本例中为QMainWindow,并使用Ui_MainWindow作为接口,还建议您使用装饰器@QtCore.pyqtSlot(),因为这样可以节省资源并避免信号过载的问题。

class MainWindowUI(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.model = Model()
def setupUi(self, mainWindow):
super().setupUi(mainWindow)
def debugPrint(self, msg):
self.textEdit.append(msg)
def refreshAll(self):
self.lineEdit.setText(self.model.getFileName())
self.textEdit.setText(self.model.getFileContents())
@QtCore.pyqtSlot()
def returnPressedSlot(self):
self.debugPrint('Return key pressed')
@QtCore.pyqtSlot()
def importSlot(self):
self.debugPrint('Import button pressed')
@QtCore.pyqtSlot()
def browseSlot(self):
self.debugPrint('Browse button pressed')
def main():
app = QtWidgets.QApplication(sys.argv)
w = MainWindowUI()
w.show()
sys.exit(app.exec_())
if __name__ == '__main__': main()

PyQt 5设计器生成扩展名为.ui的文件。该文件包含xml代码,可以使用pyuic5命令将其转换为Python代码。pyuic5命令生成一个扩展名为.py的文件。

但每次运行pyuic5命令时,它都会覆盖对Python文件所做的任何更改。为了防止这种情况,我们需要将生成的Python文件中的"main"代码复制到一个单独的文件中,然后将该文件用作我们的主程序文件。在这个文件中,我们可以导入pyuic5命令生成的Python类。我们也可以在这个文件中添加我们的自定义插槽

这种将Qt Desginer代码与自定义代码分离的做法是很好的Qt编程实践。这已经在视频电子书的第3节中提出:"使用PyQt5的Python GUI编程食谱"。

最新更新