Как четко разделить код программы и дизайна в PyQT?

В моем представлении удобно разделять код с дизайном из Qt Designer и основным кодом приложения, чтобы при изменения в Qt Designer можно было практически одним кликом заменить отдельный файл дизайна или код в нем.
А все connect'ы и функции по изменению окна и прочего были в основном файле.
Это реально сделать таким образом?

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QObject, pyqtSignal, Qt
import extGUI


class secondFlow(QtCore.QThread):  # 2 поток с автозапуском метода run при старте потока
    signalFromSecondFlow = QtCore.pyqtSignal(int)

    def __init__(self, parent=None):
        super().__init__(parent)

    def run(self):  # автоматически запускается при старте потока
        n = 1
        while n > 0:
            print('поточу поточу')
            n = n + 1
            # print(n)
            self.signalFromSecondFlow.emit(n)
            self.msleep(100)


class mainGUI(extGUI.Ui_MainWindow):
    def __init__(self, parent=None):



        self.signalFromSecondFlow.connect(self.changeFun)

        secondFlow.start()

        def changeFun(self, num):
            self.changName.setNum(num)
            print('pololo')


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('Fusion')
    ex = extGUI.Ui_MainWindow()
    w = QtWidgets.QMainWindow()
    ex.setupUi(w)
    w.show()
    sys.exit(app.exec_())

Код из Designer:

    import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(165, 124)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 160, 80))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.changName = QtWidgets.QLabel(self.verticalLayoutWidget)
        self.changName.setObjectName("counBeach")
        self.verticalLayout.addWidget(self.changName)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 165, 21))
        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", "MainWindow"))
        self.changName.setText(_translate("MainWindow", "TextLabel"))

Ответы (1 шт):

Автор решения: S. Nick

Создайте другой класс, который наследуется от соответствующего виджета, и используйте созданный в Qt Designer класс для его заполнения.

q1425649_main.py

import sys
#from PyQt5 import QtCore, QtGui, QtWidgets

from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout
from PyQt5.QtCore import QObject, pyqtSignal, Qt, QThread
from PyQt5.QtGui import QFont

#import q1425649_extGUI
from q1425649_extGUI import Ui_MainWindow

# --> S
class SecondFlow(QThread):  # 2 поток с автозапуском метода run при старте потока
    signalFromSecondFlow = pyqtSignal(int)

    def __init__(self, parent=None):
        super().__init__(parent)

    def run(self):          # автоматически запускается при старте потока
        n = 1
        while n > 0:
            print('поточу поточу')
            n = n + 1
            # print(n)
            self.signalFromSecondFlow.emit(n)
            self.msleep(500)


#class mainGUI(q1425649_extGUI.Ui_MainWindow):
class MainWindow(QMainWindow, Ui_MainWindow):                        # +++ 
    def __init__(self):
        super().__init__()                                           # +++
        self.setupUi(self)                                           # +++
        
        self.mainLayout = QHBoxLayout(self.centralwidget)            # +++
        self.mainLayout.addWidget(self.verticalLayoutWidget)         # +++
        
        self.changName.setAlignment(Qt.AlignCenter)                  # +++
        
        self.secondFlow = SecondFlow()                               # +++
#        self.signalFromSecondFlow.connect(self.changeFun)
        self.secondFlow.signalFromSecondFlow.connect(self.changeFun) # +++

#        secondFlow.start()
        self.secondFlow.start()                                      # +++

#   <----     
    def changeFun(self, num):
        self.changName.setNum(num)
        print('pololo')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    
    app.setFont(QFont("Times", 17, QFont.Bold))                     # +++
    
#    ex = q1425649_extGUI.Ui_MainWindow()
#    w = QtWidgets.QMainWindow()
#    ex.setupUi(w)

    w = MainWindow()                                                 # +++
    w.show()
    sys.exit(app.exec_())

q1425649_extGUI.py

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(165, 124)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        
        self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 160, 80))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.changName = QtWidgets.QLabel(self.verticalLayoutWidget)
        self.changName.setObjectName("counBeach")
        self.verticalLayout.addWidget(self.changName)
        
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 165, 21))
        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", "MainWindow"))
        self.changName.setText(_translate("MainWindow", "TextLabel"))
        

введите сюда описание изображения

→ Ссылка