关于python图形化界面pyside6的UI问题

我使用pyside6的QT Designer制作了图形界面,并且转换成了py文件,在主程序中使用“类”可以正常工作,但我不想把整个程序都写到这一个类里面,如果写外部函数又调用不了类里面的按钮,文本框等(比如禁用按钮,设置文本显示)。
我的问题是:
1如何不使用“类”来实现 按钮连接函数 和 窗口的正常显示与工作,请给出简明的示例代码。
2如果用“类”,那么如何用外部函数来设置按钮禁用和文本内容显示,请给出简明示例代码。
3主程序中的self.setupUi(self)是什么意思?(为什么要写这句)
十分感谢!

主程序

class Widget(QWidget, Ui_Form):
    def __init__(self):  
        super().__init__()  
        self.setupUi(self)
        self.tsb.clicked.connect(self.testspeed)  

    def speed(self):
        self.cs.setText("测速中") 
        self.cs.setEnabled(False)  
        self.info.setText('测速中。。。')
        self.sccs_thread = Thread(target=self.sccs)  # 建立线程实例
        self.sccs_thread.start()  # 开启线程
        

界面文件

class Ui_Form(object):
    def setupUi(self, Form):
        if not Form.objectName():
            Form.setObjectName(u"Form")
        Form.resize(989, 997)
        #测速按钮
        self.tsb = QPushButton(Form)
        self.tsb.setObjectName(u"cs")
        self.tsb.setFont(font)
        #信息显示窗口
        self.info = QTextBrowser(Form)
        self.info.setObjectName(u"info")
        self.info.setFont(font)


类实例化以后,不论你怎么都可以调用类的控件,函数里面你可以传参啊
如果不使用类,ui还是一个类,实例化以后,直接调用就行。
面向对象编程,代码多了,最好是分文件的。所以最后实际上很少会再单独写一个函数去调用主界面的控件,都是写成类的形式。
self.setupUi(self)就是对界面初始化
单独Ui文件(ui_form.py)

class Ui_Widget(object):
    def setupUi(self, Widget):
        if not Widget.objectName():
            Widget.setObjectName(u"Widget")
        Widget.resize(800, 600)
        self.frame = QFrame(Widget)
        self.frame.setObjectName(u"frame")
        self.frame.setGeometry(QRect(80, 100, 641, 351))
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)
        self.tsb = QPushButton(self.frame)
        self.tsb.setObjectName(u"tsb")
        self.tsb.setGeometry(QRect(60, 40, 82, 28))
        self.info = QTextBrowser(self.frame)
        self.info.setObjectName(u"info")
        self.info.setGeometry(QRect(200, 40, 256, 192))

        self.retranslateUi(Widget)

        QMetaObject.connectSlotsByName(Widget)
    # setupUi

    def retranslateUi(self, Widget):
        Widget.setWindowTitle(QCoreApplication.translate("Widget", u"Widget", None))
        self.tsb.setText(QCoreApplication.translate("Widget", u"PushButton", None))

主程序

# This Python file uses the following encoding: utf-8
import sys
import time
from PySide6.QtWidgets import QApplication, QWidget,QHBoxLayout
from PySide6.QtCore import QThread
from thread import TestSpeed
# Important:
# You need to run the following command to generate the ui_form.py file
#     pyside6-uic form.ui -o ui_form.py, or
#     pyside2-uic form.ui -o ui_form.py
from ui_form import Ui_Widget

class Widget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_Widget()
        self.ui.setupUi(self)
        main_layout=QHBoxLayout()
        self.ui.frame.setLayout(main_layout)
        main_layout.addWidget(self.ui.tsb)
        main_layout.addWidget(self.ui.info)
        self.ui.tsb.setText("测速")
        self.ui.tsb.clicked.connect(self.speed)
        #线程初始化,子线程完成测试后,发信号给主界面。
        self.thread = QThread()
        self.test_thread=TestSpeed(self)
        self.test_thread.moveToThread(self.thread)
        self.test_thread._signal.connect(self.reflash)

    def speed(self):
        self.ui.tsb.setEnabled(False)
        self.ui.info.setText('测速中。。。')
        self.test_thread.start()

    def reflash(self):
        self.ui.info.setText('测速完毕')
        self.ui.tsb.setEnabled(True)

def setText(Widget):
    Widget.ui.info.setText("准备测速")
    Widget.ui.tsb.setEnabled(True)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = Widget()
    setText(widget)
    widget.show()
    sys.exit(app.exec())

子线程:(thread.py)

from PySide6.QtCore import Signal,QThread
import time
#import datetime

class TestSpeed(QThread):
    #  通过类成员对象定义信号对象
    _signal = Signal()

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

    def __del__(self):
        self.wait()

    def run(self):
        time.sleep(1)
        for i in range(3):

            self.parent.ui.info.append(f"{i+1}秒")
            time.sleep(1)
        self._signal.emit()


最终效果:

img

img

img

如果不使用类,可以在主程序中直接实例化界面文件中的组件,并连接信号和槽。示例代码如下:

def testspeed():
    print("测速中")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = Ui_Form()
    form.tsb.clicked.connect(testspeed)
    form.show()
    sys.exit(app.exec_())


如果使用类,可以在外部函数中传入类的实例,通过实例访问类中的组件。示例代码如下:

class Widget(QWidget, Ui_Form):
    def __init__(self):  
        super().__init__()  
        self.setupUi(self)
        self.tsb.clicked.connect(self.testspeed)  

def disable_button(widget):
    widget.tsb.setEnabled(False)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = Widget()
    disable_button(widget)
    widget.show()
    sys.exit(app.exec_())



self.setupUi(self) 是将界面文件中定义的组件和布局应用到类的实例上,使得类的实例可以显示界面并对组件进行操作。

通常来说,可以在主程序中实例化图形界面的类,通过信号与槽的连接实现界面交互。
可以参考以下例程及博客:Python 小白从零开始 PyQt5 项目实战(8)汇总篇(完整例程)


from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
import uiDemo3  # 导入图像界面设计文件

if __name__ == '__main__':
    app = QApplication(sys.argv)  # 创建应用程序对象
    MainWindow = QMainWindow()  # 创建主窗口
    ui = uiDemo3.Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()  # 显示主窗口
    sys.exit(app.exec_())  # 在主线程中退出