PyQt5|GUI程序框架[B]

1.使用Ui_FormHello类的GUI程序框架

编写一个程序文件appMain1.py,它演示了使用Ui_FormHello类创建GUI应用程序的基本框架,其代码如下:

## appMain1.py
## 使用ui_FormHello.py文件中的类Ui_FormHello创建app
import sys
from PyQt5 import QtWidgets
import ui_FormHello

#用QApplication类创建了应用程序实例app
app = QtWidgets.QApplication(sys.argv)
baseWidget=QtWidgets.QWidget()    #创建窗体的基类QWidget的实例

#使用ui_FormHello模块中的类Ui_FormHello创建了一个对象ui
ui =ui_FormHello.Ui_FormHello()
ui.setupUi(baseWidget)    #以baseWidget作为传递参数,创建完整窗体

#显示窗体
baseWidget.show()
##ui.LabHello.setText("Hello,被程序修改")    #可以修改窗体上标签的文字
sys.exit(app.exec_())

Ui_FormHello类的setupUi()函数只创建窗体上的其他组件,而作为容器的窗体靠外部传入的,这里的baseWidget就是作为一个基本的QWidget窗体传入的。执行这条语句后,就在窗体baseWidget上创建了标签和按钮

窗体上的标签对象LabHello是在Ui_FormHello类里定义的公共属性,所以在程序里可以通过ui对象访问LabHello。
对appMain1.py文件稍作修改,在baseWidget.show()语句后加入一条语句,如下(省略了前后的语句):

baseWidget.show()
ui.LabHello.setText("Hello,被程序修改")
----------------------------------------
#错误的
#baseWidget.LabHello.setText("Hello,被程序修改")  

baseWidget是QWidget类型的对象,它只是LabHello的父容器,并没有定义公共属性LabHello,所以运行时会出错。而ui是Ui_FormHello类的实例对象,窗体上的所有界面组件都是ui的实例属性。因此,访问窗体上的界面组件只能通过ui对象。


1.1 界面与逻辑分离的GUI程序框架

若要基于UI窗体设计更多的业务逻辑,由于appMain1.py是一个过程化的程序,难以实现业务逻辑功能的有效封装
界面与业务逻辑分离的设计方法不是唯一的,这里介绍两种方法,一种是多继承方法,另一种是单继承方法

1. 多继承方法

## appMain2.py  多继承方法
import sys
from PyQt5.QtWidgets import  QWidget, QApplication
from ui_FormHello import Ui_FormHello


#采用多继承的方式定义了一个类QmyWidget,称这个类为窗体的业务逻辑类,它的父类是QWidget和Ui_FormHello
class QmyWidget(QWidget, Ui_FormHello):
    def __init__(self, parent=None):
        super().__init__(parent)       #调用父类构造函数,创建QWidget窗体

                                       #在多继承时,使用super()得到的是第一个基类,在这里就是QWidget。所以,执行这条语句后,self就是一个QWidget对象。

        self.Lab="多重继承的QmyWidget"    #新定义的一个变量
        self.setupUi(self)    #self是QWidget窗体,可作为参数传给setupUi(),作为各组件的窗体容器
        self.LabHello.setText(self.Lab)

if  __name__ == "__main__":
    app = QApplication(sys.argv)    #创建app
    myWidget=QmyWidget()
    myWidget.show()
    myWidget.btnClose.setText("不关闭了")
    sys.exit(app.exec_())

通过这样的多继承,Ui_FormHello类中定义的窗体上的所有界面组件对象就变成了新定义的类QmyWidget的公共属性,可以直接访问这些界面组件。

这种多继承方式有其优点,也有其缺点,表现为以下两方面:

(1)界面上的组件都成为窗体业务逻辑类QmyWidget的公共属性,外界可以直接访问。优点是访问方便,缺点是过于开放,不符合面向对象严格封装的设计思想。
(2)界面上的组件与QmyWidget类里新定义的属性混合在一起了,不便于区分。例如,在构造函数中有这样一条语句:

    self.LabHello.setText(self.Lab)

其中,self.LabHello是窗体上的标签对象,而self.Lab是QmyWidget类里新定义的一个属性。如果没有明确的加以区分的命名规则,当窗体上的界面组件较多,且窗体业务逻辑类里定义的属性也很多时,就难以区分哪个属性是界面上的组件,哪个属性是在业务逻辑类里新定义的,这样是不利于界面与业务逻辑分离的。

总结

#参考关系 相框的外框是QWidget窗体的对象QmyWidget--》窗体里面要装一个相片,相片是Ui_FormHello类的一个对象(QmyWidget.setupUi(self))--》相片上的内容是我们自己可以定义的,但是因为是要看相片上的内容而不是相框上的内容,所以我们把相框上的内容比作Ui_FormHello类对象(QmyWidget.setupUi(self))的公共属性--》也就是说只有我们访问相片的(Ui_FormHello类的对象QmyWidget.setupUi(self))属性才能看见我们想看到的东西而不是直接访问QmyWidget

如果要看整个相框就直接QWidget.show(),直接把整个相框老兄展示出去


2. 单继承与界面独立封装方法

PyQt5|GUI程序框架[B]插图
## appMain.py单继承方法,能更好地进行界面与逻辑的分离
import sys
from PyQt5.QtWidgets import  QWidget, QApplication
from ui_FormHello import Ui_FormHello


class QmyWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)      #调用父类构造函数,创建QWidget窗体
        self.__ui=Ui_FormHello()       #创建UI对象
        self.__ui.setupUi(self)        #构造UI
        self.Lab="单继承的QmyWidget"
        self.__ui.LabHello.setText(self.Lab)


    def setBtnText(self, aText):
        self.__ui.btnClose.setText(aText)


if  __name__ == "__main__":
    app = QApplication(sys.argv)     #创建app,用QApplication类
    myWidget=QmyWidget()
    myWidget.show()
    myWidget.setBtnText("间接设置")
    sys.exit(app.exec_())

(1)新定义的窗体业务逻辑类QmyWidget只有一个基类QWidget
(2)在QmyWidget的构造函数中,首先调用父类(也就是QWidget)的构造函数,这样self就是一个QWidget对象
(3)显式地创建了一个Ui_FormHello类的私有属性self.__ui,即

self.__ui=Ui_FormHello()    #创建UI对象

私有属性self.__ui包含了可视化设计的UI窗体上的所有组件,所以,只有通过self.__ui才可以访问窗体上的组件,包括调用其创建界面组件的setupUi()函数。

提示 Python语言的类定义通过命名规则来限定元素对外的可见性,属性或方法名称前有两个下划线表示是私有的,一个下划线表示模块内可见,没有下划线的就是公共的。

(4)由于self.__ui是QmyWidget类的私有属性,因此在应用程序中创建的QmyWidget对象myWidget不能直接访问myWidget.__ui,也就无法直接访问窗体上的界面组件。
为了访问窗体上的组件,可以在QmyWidget类里定义接口函数,例如函数setBtnText()用于设置窗体上按钮的文字。在应用程序里创建QmyWidget对象的实例myWidget,通过调用setBtnText()函数间接修改界面上按钮的文字,即

myWidget.setBtnText("间接设置")

仔细观察和分析这种单继承的方式,发现它有如下特点。
(1)可视化设计的窗体对象被定义为QmyWidget类的一个私有属性self.__ui,在QmyWidget类的内部对窗体上的组件的访问都通过这个属性实现,而外部无法直接访问窗体上的对象,这更符合面向对象封装隔离的设计思想。
(2)窗体上的组件不会与QmyWidget里定义的属性混淆。例如,下面的语句:

self.__ui.LabHello.setText(self.Lab)

self.__ui.LabHello表示窗体上的标签对象LabHello,它是self.__ui的一个属性;self.Lab是QmyWidget类里定义的一个属性。这样,窗体上的对象和QmyWidget类里新定义的属性不会混淆,有利于界面与业务逻辑的分离。
(3)也可以定义界面对象为公共属性,即创建界面对象时用下面的语句:

self.ui=Ui_FormHello()

这里的ui就是个公共属性,在类的外部也可以通过属性ui直接访问界面上的组件
单继承方法更有利于界面与业务逻辑分离

版权声明:
作者:RHZ
链接:https://www.rhzhz.cn/?p=599
来源:RHZ | 用文字记录工作和学习生活
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
海报
PyQt5|GUI程序框架[B]
1.使用Ui_FormHello类的GUI程序框架 编写一个程序文件appMain1.py,它演示了使用Ui_FormHello类创建GUI应用程序的基本框架,其代码如下: ## appMa……
<<上一篇
下一篇>>