第三篇 -- 界面与逻辑分离的设计方法(多继承方法和单继承方法)
分类:
IT文章
•
2023-12-17 18:56:19
一、多继承方法
1. 画图Form.ui,生成Form.py
UI:

Form.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Form.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
self.label = QtWidgets.QLabel(Form)
self.label.setGeometry(QtCore.QRect(110, 100, 181, 31))
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
self.label.setFont(font)
self.label.setObjectName("label")
self.btnClose = QtWidgets.QPushButton(Form)
self.btnClose.setGeometry(QtCore.QRect(160, 180, 75, 23))
self.btnClose.setObjectName("btnClose")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Demo2_2"))
self.label.setText(_translate("Form", "Hello, by UI Designer"))
self.btnClose.setText(_translate("Form", "关闭"))
View Code
2. 多继承方法导入界面Form.py
appMain2.py
# # appMain2.py 多继承方法
"""
多继承方式优缺点:
1. 界面上的组件都成为窗体业务逻辑类QmyWidget的公共属性,外界可以直接访问。优点是访问方便,缺点是过于开放,
不符合面向对象严格封装的设计思想
2. 界面上的组件与QmyWidget类里新定义的属性混合在一起了,不便于区分。当窗体上的界面组件较多,
且窗体业务逻辑类里定义的属性也很多时,就难以区分哪个属性是界面上的组件,哪个属性是在业务逻辑类里新定义的,
这样不利于界面与业务逻辑分离。
"""
import sys
from PyQt5.QtWidgets import QWidget, QApplication
from Form import Ui_Form
class QmyWidget(QWidget, Ui_Form):
def __init__(self, parent=None):
super().__init__(parent) # 调用父类构造函数,创建QWidget窗体
self.Lab = "多重继承的QmyWidget" # 新定义的一个变量
self.setupUi(self) # self是QWidget窗体,可作为参数传给setupui()
self.label.setText(self.Lab)
if __name__ == "__main__":
app = QApplication(sys.argv) # 创建app
myWidget = QmyWidget()
myWidget.show()
myWidget.btnClose.setText("不关闭了")
sys.exit(app.exec_())
View Code
3. 多继承解析:
a. 采用多继承的方式定义了一个类QmyWidget,称这个类为窗体的业务逻辑类,它的父类是QWidget和Ui_Form。
b. 在这个类的构造函数中,首先用函数super()获取父类,并执行父类的构造函数,代码是super().__init__(parent),在多继承时,使用super()得到的是第一个基类,在这里就是QWidget。所以,执行这条语句后,self就是一个QWidget对象。
c. 调用setUi()函数创建UI窗体,即self.setupUi(self)。因为QmyWidget的基类包括Ui_Form类,所以可以调用Ui_Form类的setupUi()函数。同时,经过前面调用父类的构造函数,self是一个QWidget对象,可以作为参数传递给setupUi()函数,正好作为各组件的窗体容器。
d. 通过这样的多继承,Ui_Form类中定义的窗体上的所有界面组件对象就变成了新定义的类QmyWidget的公共属性,可以直接访问这些界面组件。
二、单继承与界面独立封装方法
1. 同样写一个界面,同多继承一样Form.py
2. 单继承方法导入界面Form.py
appMain.py
# # appMain.py 单继承方法,能更好地进行界面与逻辑的分离
import sys
from PyQt5.QtWidgets import QWidget, QApplication
from Form import Ui_Form
class QmyWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent) # 调用父类构造函数,创建QWidget窗体
self.__ui = Ui_Form() # 创建UI对象
self.__ui.setupUi(self) # 构造UI
self.Lab = "单继承的QmyWidget"
self.__ui.label.setText(self.Lab)
def set_btn_text(self, a_text):
self.__ui.btnClose.setText(a_text)
if __name__ == "__main__":
app = QApplication(sys.argv) # 创建app,用QApplication类
myWidget = QmyWidget()
myWidget.show()
myWidget.set_btn_text("间接设置")
sys.exit(app.exec_())
View Code
3. 单继承解析
a. 新定义的窗体业务逻辑类QmyWidget只有一个基类QWidget。
b. 在QmyWidget的构造函数中,首先调用父类(也就是QWidget)的构造函数,这样self就是一个QWidget对象
c. 显式地创建了一个Ui_Form类的私有属性self.__ui,即self.__ui = Ui_Form。私有属性self.__ui包含了可视化设计的UI窗体上的所有组件,所以,只有通过self.__ui才可以访问窗体上的组件,包括调用其创建界面组件的setupUi()函数
注:Python语言的类定义通过命名规则来限定元素对外的可见性,属性或方法名称前有两个下划线表示是私有的,一个下划线表示模块内可见,没有下划线的就是公共的。
d. 由于self.__ui是QmyWidget类的私有属性,因此在应用程序中创建的QmyWidget对象myWidget不能直接访问myWidget.__ui,也就无法直接访问窗体上的界面组件。为了访问窗体上的组件,可以在QWidget类里定义接口函数,例如set_btn_text()用于设置窗体上按钮的文字。在应用程序里创建QmyWidget对象的实例myWidget,通过调用set_btn_text()函数间接修改界面上按钮的文字,即myWidget.set_btn_text("间接设置")
4. 单继承特点
a. 可视化设计的窗体对象被定义为QmyWidget类的一个私有属性self.__ui,在QmyWidget类的内部对窗体上的组件的访问都通过这个属性实现,而外部无法直接访问窗体上的对象,这更符合面向对象封装隔离的设计思想。
b. 窗体上的组件不会与QmyWidget里定义的属性混淆,例如self.Lab和self.__ui.label,有利于界面与业务逻辑的分离。
c. 当然,也可以定义界面对象为公共属性,即创建界面对象时用下面的语句:self.ui = Ui_Form(),这里的ui就是个公共属性,在类的外部也可以通过属性ui直接访问界面上的组件
总结:对比多继承方法和单继承方法,可以发现单继承方法更有利于界面与业务逻辑分离。