zoukankan      html  css  js  c++  java
  • 第三篇 -- 界面与逻辑分离的设计方法(多继承方法和单继承方法)

    一、多继承方法

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

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

  • 相关阅读:
    剑指Offer——构建乘积数组
    剑指Offer——把二叉树打印成多行
    剑指Offer——二叉树的下一个结点
    剑指Offer——二叉搜索树与双向链表
    剑指Offer——二叉搜索树的后序遍历序列
    LeetCode——Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode——Construct Binary Tree from Preorder and Inorder Traversal
    剑指Offer——重建二叉树2
    C++ STL基本容器的使用
    mysql中模糊查询的四种用法介绍
  • 原文地址:https://www.cnblogs.com/smart-zihan/p/12632705.html
Copyright © 2011-2022 走看看