Python Qt GUI与数据可视化编程
上QQ阅读APP看书,第一时间看更新

2.7 3个单窗体GUI项目模板

2.7.1 概述

本书的示例程序大部分只有一个窗体,并且采用可视化方法设计窗体UI文件。窗体的常用基类是QWidget、QDialog和QMainWindow,示例Demo2_2中使用的是基于QDialog的窗体,示例Demo2_5中使用的是基于QWidget的窗体。

为了便于读者创建新的示例项目进行编程练习,我们创建了3个单窗体GUI应用程序模板,存放在随书示例程序的“\AppTemplates”目录下。这个目录下有以下3个模板项目文件夹。

· \dialogApp目录,是一个主窗体基于QDialog的应用程序模板。

· \widgetApp目录,是一个主窗体基于QWidget的应用程序模板。

· \mainWindowApp目录,是一个主窗体基于QMainWindow的应用程序模板。

2.7.2 dialogApp项目模板

dialogApp项目是主窗体基于QDialog的项目模板,项目目录下的文件及其子目录\QtApp里的文件如图2-34所示。

图2-34 dialogApp模板目录下文件(左)及其子目录\QtApp下的文件(右)

子目录\QtApp里是一个Qt GUI应用程序项目,\QtApp\images目录下是Qt项目资源文件用到的一些图标和图片文件。Qt项目文件是QtApp.pro,窗体文件是Dialog.ui。使用Qt Creator打开项目QtApp.pro后的主要工作是可视化设计窗体文件Dialog.ui,利用Go to slot对话框为界面上的组件的信号生成槽函数框架,以便复制槽函数名。

dialogApp项目目录下的批处理文件uic.bat用于编译UI窗体文件和资源文件,双击此文件就可以完成编译,分别生成文件ui_Dialog.py和res_rc.py。uic.bat文件的内容如下:

        echo off


        rem将子目录QtApp下的.ui文件复制到当前目录下,并且编译
        copy .\QtApp\Dialog.ui  Dialog.ui
        pyuic5-o ui_Dialog.py  Dialog.ui


        rem编译并复制资源文件
        pyrcc5 .\QtApp\res.qrc -o res_rc.py

文件myDialog.py是与Dialog.ui对应的窗体业务逻辑类QmyDialog所在的文件,这个文件的内容如下:

        # -*- coding: utf-8-*-
        import sys
        from PyQt5.QtWidgets import  QApplication, QDialog
        ##from PyQt5.QtCore import  pyqtSlot, pyqtSignal, Qt
        ##from PyQt5.QtWidgets import
        ##from PyQt5.QtGui import
        ##from PyQt5.QtSql import
        ##from PyQt5.QtMultimedia import
        ##from PyQt5.QtMultimediaWidgets import


        from ui_Dialog import Ui_Dialog
        class QmyDialog(QDialog):
            def __init__(self, parent=None):
              super().__init__(parent)    #调用父类构造函数,创建窗体
              self.ui=Ui_Dialog()         #创建UI对象
              self.ui.setupUi(self)       #构造UI


        ##  ============自定义功能函数=============================
        ##  ===========事件处理函数=============================


        ##  ========由connectSlotsByName()自动关联的槽函数=========


        ##  ==========自定义槽函数================================


        ##  ============窗体测试程序 =============================
        if  __name__ == "__main__":         ##用于当前窗体测试
            app = QApplication(sys.argv)     #创建GUI应用程序
            form=QmyDialog()                  #创建窗体
            form.show()
            sys.exit(app.exec_())

这个文件里定义了窗体业务逻辑类QmyDialog,在构造函数里已经有创建窗体的代码。QmyDialog的代码分为几部分,分别用于添加各种函数代码。

文件myDialog.py里还有窗体测试程序,所以可以直接运行myDialog.py文件以测试QmyDialog类的功能。

文件appMain.py是将文件myDialog.py中的窗体测试部分的程序单独拿出来作为一个文件。在具有多个窗体的GUI项目里,appMain.py文件的代码创建主窗体然后运行应用程序。

2.7.3 widgetApp项目模板

widgetApp项目是主窗体基于QWidget的项目模板,项目目录下的文件及其子目录\QtApp里的文件如图2-35所示。

图2-35 widgetApp模板目录下文件(左)及其子目录\QtApp下的文件(右)

子目录\QtApp里是一个Qt GUI应用程序项目,Qt项目文件是QtApp.pro,窗体UI文件是Widget.ui。

widgetApp项目目录下的批处理文件uic.bat用于编译UI窗体文件和资源文件,双击此文件就可以完成编译,分别生成文件ui_Widget.py和res_rc.py。uic.bat文件的内容如下。

        echo off


        rem将子目录QtApp下的.ui文件复制到当前目录下,并且编译
        copy .\QtApp\Widget.ui  Widget.ui
        pyuic5-o ui_Widget.py  Widget.ui


        rem编译并复制资源文件
        pyrcc5 .\QtApp\res.qrc -o res_rc.py

文件myWidget.py是与Widget.ui对应的窗体业务逻辑类QmyWidget所在的文件,这个文件的内容如下。

        # -*- coding: utf-8-*-
        import sys
        from PyQt5.QtWidgets import  QApplication, QWidget
        ##from PyQt5.QtCore import  pyqtSlot, pyqtSignal, Qt
        ##from PyQt5.QtWidgets import
        ##from PyQt5.QtGui import
        ##from PyQt5.QtSql import
        ##from PyQt5.QtMultimedia import
        ##from PyQt5.QtMultimediaWidgets import


        from ui_Widget import Ui_Widget
        class QmyWidget(QWidget):
            def __init__(self, parent=None):
              super().__init__(parent)    #调用父类构造函数,创建窗体
              self.ui=Ui_Widget()         #创建UI对象
              self.ui.setupUi(self)       #构造UI


        ##  ==============自定义功能函数============================


        ##  ==============事件处理函数===========================


        ##  ==========由connectSlotsByName()自动关联的槽函数========


        ##  =============自定义槽函数==============================


        ##  ============窗体测试程序 ==============================
        if  __name__ == "__main__":        ##用于当前窗体测试
            app = QApplication(sys.argv)    #创建GUI应用程序
            form=QmyWidget()                 #创建窗体
            form.show()
            sys.exit(app.exec_())

2.7.4 mainWindowApp项目模板

mainWindowApp项目是主窗体基于QMainWindow的项目模板,项目目录下的文件及其子目录\QtApp里的文件如图2-36所示。

图2-36 mainWindowApp模板目录下文件(左)及其子目录\QtApp下的文件(右)

子目录\QtApp里的Qt项目的窗体文件是MainWindow.ui,用Qt Creator可视化设计窗体MainWindow.ui并生成界面组件的槽函数框架。

项目目录下的批处理文件uic.bat用于编译UI窗体文件和资源文件,双击此文件就可以完成编译,分别生成文件ui_MainWindow.py和res_rc.py。uic.bat文件的内容如下。

        echo off


        rem将子目录QtApp下的.ui文件复制到当前目录下,并且编译
        copy .\QtApp\MainWindow.ui  MainWindow.ui
        pyuic5-o ui_MainWindow.py  MainWindow.ui


        rem编译并复制资源文件
        pyrcc5 .\QtApp\res.qrc -o res_rc.py

文件myMainWindow.py是与窗体MainWindow.ui对应的窗体业务逻辑类QmyMainWindow所在的文件,这个文件的内容如下:

        # -*- coding: utf-8-*-
        import sys
        from PyQt5.QtWidgets import  QApplication, QMainWindow
        ##from PyQt5.QtCore import  pyqtSlot, pyqtSignal, Qt
        ##from PyQt5.QtWidgets import
        ##from PyQt5.QtGui import
        ##from PyQt5.QtSql import
        ##from PyQt5.QtMultimedia import
        ##from PyQt5.QtMultimediaWidgets import


        from ui_MainWindow import Ui_MainWindow
        class QmyMainWindow(QMainWindow):
            def __init__(self, parent=None):
              super().__init__(parent)    #调用父类构造函数,创建窗体
              self.ui=Ui_MainWindow()     #创建UI对象
              self.ui.setupUi(self)       #构造UI
        ##  ==============自定义功能函数============================


        ##  ==============事件处理函数===========================


        ##  ==========由connectSlotsByName()自动关联的槽函数========


        ##  =============自定义槽函数==============================


        ##  ============窗体测试程序 ===============================
        if __name__ == "__main__":         ##用于当前窗体测试
            app = QApplication(sys.argv)     #创建GUI应用程序
            form=QmyMainWindow()              #创建窗体
            form.show()
            sys.exit(app.exec_())

2.7.5 使用项目模板和实例源程序

本书的示例程序都使用IDLE编写和运行,这3个项目模板中的uic.bat完全控制了窗体UI文件和资源文件到Python文件的编译过程,当UI文件多于一个,或UI文件名不同于模板中的UI文件名时,直接修改uic.bat文件的内容即可。

PyQt5应用程序的开发主要有两项工作内容:一项是窗体的UI设计,这主要在UI Designer里可视化设计完成;另一项是对应的窗体业务逻辑类的功能实现,也就是在3个项目模板的myDialog.py、myWidget.py和myMainWindow.py文件里编写功能实现代码。

读者在学习本书时,如果要自己完成完整示例,可以从这3个项目模板中直接复制一个作为自己的项目,然后可视化设计UI窗体,在业务逻辑类里编写功能实现代码。

本书提供了两套示例源程序,其中一套是具有全部源码的程序,包括Qt项目、UI窗体、Python程序等,实现窗体业务逻辑操作的Python程序文件可以直接运行出结果。使用这套源程序可以查看示例运行结果,查看已设计好的UI窗体,也可以查看Python程序文件中的功能实现代码。

另一套是不完整的程序,包括Qt项目、UI窗体和Python程序文件,但是实现窗体业务逻辑操作的Python程序文件只有基本代码框架,而没有功能实现代码。这套程序是为了便于读者使用已经设计好的UI窗体,根据书上的介绍内容和过程,在Python程序框架里自己编写程序,逐步实现功能。之所以保留UI窗体,是因为UI窗体的可视化设计是个比较耗时间的过程,读者如果自己从头开始设计UI窗体,难以保证所有组件的名称和属性与示例的一致,而使用已经设计好的UI窗体进行编程学习就可以避免这些问题,将学习的重点放在类的各种接口属性和函数的使用,以及业务逻辑功能的实现上。

2.7.6 在Eric中编辑和运行示例程序

本书的示例程序都使用IDLE编写和运行,而没有使用另一种常用的Python编程IDE软件Eric。项目模板中使用批处理文件uic.bat可以让读者更清楚掌握UI文件、Qt资源文件到Python文件的编译过程。另外,Eric有以下一些问题。

· Eric在针对UI窗体文件生成业务逻辑类时使用多继承,多继承在界面与业务逻辑分离方面不如单继承好(参见2.2.4节)。

· Eric在为界面组件的信号生成槽函数时需要在一个对话框上选择组件及其信号,对话框上列出了所有界面组件的名称及其信号,这样的选择不如在UI Designer里选择一个组件然后使用Go to slot对话框生成槽函数框架直观和快捷,特别是在界面组件非常多时。

但Eric也有其优势,例如代码导航功能比较好,代码提示和自动完成功能较强,这些是IDLE的劣势。熟悉Eric的读者可以为本书的示例项目创建一个Eric项目保存到示例项目的文件夹下,然后添加示例的程序文件,将Qt Creator、批处理文件uic.bat和Eric结合起来用,具体的用法如下。

· 在Qt Creator中使用UI Designer可视化设计窗体UI文件。

· 运行uic.bat编译窗体UI文件和资源文件。

· 在UI Designer中使用Go to slot对话框为组件的信号生成槽函数框架,复制函数名到Eric中定义槽函数并编写功能实现代码。

· 在Eric中编辑Python程序文件,充分利用Eric的代码导航、代码提示和自动完成等功能。

· 在Eric里调试和运行程序。

这样可以综合各个软件和方法的优点。例如,将示例项目Demo2_3的整个目录复制为示例Demo2_6,然后在示例根目录下创建一个Eric6的项目文件EricProject,将根目录下的所有文件都添加到这个Eric6项目,然后就可以在Eric6软件里编辑、调试和运行程序了。图2-37是在Eric6里管理示例项目Demo2_6的界面。

图2-37 在Eric6里管理示例Demo2_6

由于本书的示例程序一般不是太复杂,代码行数不多,因此使用IDLE来编程和运行测试。熟悉Eric6,或对使用Eric6管理项目感兴趣的读者可以使用Eric6来编程。