• 从开发流程看 PyQt5 入门


    从开发流程看 PyQt5 入门

      近期笔者开发了几个基于PyQt5的小项目,也算是对PyQt5及其开发流程有了一定的了解,故想以备忘的目的记录下来,供各位读者和自己参考。

      本文将以PyQt5的开发流程为线索,介绍基本PyQt5图形界面应用的基本功能和原理,并拓展相关知识,覆盖PyQt5入门所需要的各方面。其余进阶内容,读者可以借助完整的文档支持和丰富的参考资料自行探索。(有需要再查阅文档即可)

    基本介绍

    PyQt5,是跨平台图形用户界面框架Qt的Python支持包。其提供了丰富的图形控件库,与优秀的跨平台性能(包括Windows, macOS, Linux, iOS, Android)。Qt官方提供的Python支持为PySide库,但语法与PyQt基本没有差异,本文就以PyQt5为例展开。

    另外,Qt提供了跨语言的通用UI开发设计器Qt Designer,可以以图形化的方式构建UI界面,并可提供预览。设计完成的文件通过PyQt5自带的工具PyUIC转换为PyQt5代码,可被Python主逻辑直接引用。转换后的代码样例如下:

    PyUIC

    关于如何安装环境,以及转换设计文件,本文不再赘述,请读者另行搜索教程。

    窗体设计与结构

    前端的第一部分是设计UI粗稿,需要使用Qt Designer等窗体设计器。

    Qt的基类

    所有的Qt对象都是基于Object基类拓展(事实上,所有的Python类都是以object类作为缺省基类)。

    打开Qt Designer,新建项目,可以看到几种模板,分别代表了三类Qt基类:

    • QMainWindow:带有MenuBar, StatusBar, and centralwidget的窗体。
      • 自带菜单栏(一般位于应用最上部标题栏下,第一个总是File : )),状态栏(最下面一条)
      • 以上三个控件必须以window.setXXX方式指定,否则相当于没有初始化,不会在窗体上显示
      • 一般使用该类创建功能较为完整的窗体,可以省去一些初始化菜单栏等控件的时间
    • Widget:一般控件类,为不带任何初始控件的空白窗体。
      • 可以直接进行编辑,没有初始模板,但编码上较方便
      • 一般用于简单窗体
    • QDialog:顾名思义,对话框类,自定义对话框内容
      • 一般用于特殊的自定义对话框
      • Qt提供了多种样式的对话框(FileDialog等),可以直接调用,一般不需要自定义对话框

    Qt的对象结构

    Qt以树形结构组织对象。每一个初始对象(包括窗体)创建时,都需要一个Parent参数(可为空),用于指定其父对象。一般,父子关系用于表示容器控件的包含关系。例如,在QMainWindow类窗体中,所有的窗体控件都包含在CenterWidget控件中,也就以其为父对象。

    一个MenuBar的属性结构类似下图例:

    Class Structure

    控件与布局

    在Qt Designer中,所有控件被分类与控件菜单中,拖动到窗体合适位置就会创建,也可以修改大小与属性。控件的主要属性如下:

    • objectName:作为QObject的属性,为任何一个Qt对象的基本属性,缺省以控件类型与编号命名。在设计窗体时,建议同时将控件按照类型+功能的格式命名,避免产生名称混乱。
    • enabled: 控件是否可用,disable的控件为灰色,无法响应用户操作(但可以由代码控制)
    • size: 控件的尺寸,即长x宽
    • Text: (部分控件)控件上展示的文字
    • StyleSheet: 控件应用的样式表(在QSS中会使用)

    其余部分属性为控件特有,需要使用时请参阅手册。

    布局是前端设计的另一个重要部分,使用布局,我们可以有规则地安排控件,并方便地修改及调用。布局种类如下:

    • Vertical Layout: 垂直布局,控件垂直分布,并占满当前整个空间宽度
    • Horizontal Layout: 水平布局,控件水平分布,并占满当前整个空间高度
    • Grid Layout: 网格布局,控件呈网格状分布,可调网格比例
    • Form Layout: 表单分布,控件整体按照表单样式分布

    在较简单的项目中,可以不使用Layout,直接按照绝对坐标安放控件。

    后端调用

    为了使前后端分离,方便后续迭代前端布局样式、改进后端代码,降低耦合度,我们使用窗口主逻辑引用前端布局类的方式实现调用前端的功能。

    调用前端布局

    一个简单的窗体程序框架如下(以QMainWindow基类为例)

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow
    from mainWindowUI import Ui_MainWindow
    
    
    class MainWindow(QMainWindow):
       def __init__(self, parent=None) -> None:
          super(MainWindow, self).__init__(parent)
          self.ui = Ui_MainWindow()
          self.ui.setupUi(self)
    
          # Other Initialize Code
    
       def someFunction(self):
          pass
    
    
    if __name__ == '__main__':
       app = QApplication(sys.argv)
       main_window_instance = MainWindow()
       main_window_instance.show()
       sys.exit(app.exec_())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • MainWindow类继承QMainWindow基类,在初始化时必须调用其超类的初始化,super().__init__
    • 使用PyUIC转换工具将UI设计文件转换为Python文件,引用到框架中,将self.ui设置为该前端的一个实例,并调用setupUi方法,初始化窗体控件
    • 主模块中声明一个QApplication,并加入系统参数,声明一个窗体Instance,并调用show()方法显示窗体,最后使用sys.exit函数,在窗体关闭后退出

    信号连接

      信号与槽是Qt的核心机制。信号与槽的功能类似于VB.net的事件,后端逻辑通过事件捕获前端控件的各种状态,比如单击、鼠标进入、选项改变等。在Qt中,这种机制被信号与槽取代。

    • 信号:由前端的各种事件触发,自定义信号由代码触发

    • 槽:是信号的处理程序(函数),一个槽连接上信号后,每当信号被触发(emit),就会调用槽,以完成响应任务。

    • 信号与槽通过connect方法进行连接

    一般信号

      一般信号类似于事件,由前端控件的状态变化触发。可以在前端设计器中连接控件之间的简单信号,大多数需要后端处理的信号,要在主逻辑类初始化时手动进行连接。

    self.ui.pushButton.clicked.connect(MainWindow.someFunc)
    
    • 1
    • 注意:连接信号的事件不需要加括号(是信号本身),槽也不需要括号(代表函数本身)

    • 其他信号类型参阅Qt Documentation

    自定义信号

    Qt允许自定义信号,用代码可以触发该信号,并能指定信号附加参数。

    Qt5以上版本的信号需要在类中以类变量的形式提前声明:

    from PyQt5.QtCore import pyqtSignal
    
    SOME_SIGNAL = pyqtSignal()
    SOME_SIGNAL_WITH_PARAM_INT = pyqtSignal(int)
    
    • 1
    • 2
    • 3
    • 4

    使用emit方法触发自定义信号:

    SOME_SIGNAL.emit()
    SOME_SIGNAL_WITH_PARAM_INT.emit(some_int)
    
    • 1
    • 2

    信号的连接方法与一般信号相同,这里不再赘述。

    整体架构

    完整的PyQt项目一般至少由三部分构成:

    • 前端设计代码,由设计器文件转换得到
    • 后端逻辑代码,由后端编程得到
    • 主逻辑代码,通过引用前后端文件,实现窗体显示与信号连接
  • 相关阅读:
    Golang基本命令操作
    浅读-《深入浅出Nodejs》
    Wordpress页面生成器:Elementor 插件制作网站页面教程(图文完整)
    小程序 canvas 2d 绘制海报
    Python常见工厂函数用法
    什么是AIGC?
    Linux读写锁的容易犯的问题
    stable-diffusion-webui安装Wav2Lip
    【面试刷题】——Qt事件处理器级别的划分
    【办公类-22-14】周计划系列(5-5)“周计划-05 周计划表格内教案部分“节日”清空改成“节日“” (2024年调整版本)Win32
  • 原文地址:https://blog.csdn.net/Zheng__Huang/article/details/126258596