PyQt5 Designer с пользовательскими слотами - PullRequest
0 голосов
/ 27 ноября 2018

Я все еще пытаюсь выяснить 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'

Thisна самом деле имеет смысл, потому что 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"))

Ответы [ 2 ]

0 голосов
/ 02 апреля 2019

PyQt 5 Designer создает файлы с расширением .ui .Файл содержит код XML, который можно преобразовать в код Python с помощью команды pyuic5 .Команда pyuic5 создает файл с расширением .py .

Но каждый раз, когда запускается команда pyuic5, она перезаписывает любые изменения, внесенные в файл Python.Чтобы предотвратить это, нам нужно скопировать «основной» код в сгенерированном файле Python в отдельный файл, а затем использовать этот файл в качестве основного файла программы.В этом файле мы можем импортировать класс Python, сгенерированный командой pyuic5 .Мы также можем добавить наши пользовательские слоты в этот файл

Эта практика отделения кода Qt Desginer от пользовательского кода является хорошей практикой программирования на Qt.В разделе 3 видео-книги было предложено: « Рецепты программирования Python GUI с использованием PyQt5 ».

0 голосов
/ 28 ноября 2018

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()
...