第三篇 -- 界面与逻辑分离的设计方法(多继承方法和单继承方法)

一、多继承方法

  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直接访问界面上的组件

 

总结:对比多继承方法和单继承方法,可以发现单继承方法更有利于界面与业务逻辑分离。

 

posted @ 2020-04-04 17:18  o云淡风轻o  阅读(1250)  评论(0编辑  收藏  举报