Python+Qt Quick:一种便捷的桌面软件开发模式

引言

Python大家都耳熟能详,Qt Quick是自Qt 4.7发布的一种方式有别于传统的界面开发技术,从名字就能看出它追求便捷的目标。Qt Quick为Qt引入了一门叫QML(Qt Meta/Modeling Language)的脚本语言,它是ECMAScript标准的实现,意即,有着和JavaScript一样的语法(学过JS的朋友上手非常容易)。这意味着我们可以和开发网页一样开发程序界面,想想是不是还有点小激动呢。

开发平台:Windows 7/10

分享一下涉及到的资源文件:http://pan.baidu.com/s/1cpftDk

开发环境搭建

■ Python

在Python官网下载最新版(当前为3.6.1)安装包,因为最终做出来的程序最好同时能在32位和64位机器上运行,所以选择x86版本的,安装在自己喜欢的路径,比如:C:\Python\Python36-32,并加环境变量(C:\Python\Python36-32C:\Python\Python36-32\Scripts)。

■ PyQt

PyQt是Qt的Python binding,最新版本是5.8.2,可惜它在后续程序打包发布的时候存在bug(会按开发环境的绝对路径寻找PyQt控件的资源图片,结果必然是找不到),因此我找到了PyQt 5.7.1,下载wheel文件PyQt5-5.7.1-5.7.1-cp34.cp35.cp36.cp37-none-win32.whl(我保存到了D盘根目录下),安装:

pip3 install D:\PyQt5-5.7.1-5.7.1-cp34.cp35.cp36.cp37-none-win32.whl

■ Qt Creator

这是Qt提供的集成开发环境,我们用Qt Quick其实不需要靠它拖控件,直接手敲所有代码就行,但我仍建议你安装,用它编辑QML代码,有高亮、纠错、标识符匹配提选等功能,同时包含有Qt文档,可以快速查阅各个类的使用方法。

官网下载不但需要注册账号,还需要填一份承诺式的问卷,读者可以直接使用我分享的安装包。

Python+Qt Quick:一种便捷的桌面软件开发模式_第1张图片
安装时勾选「msvc2015」组件即可,因为它包含了Qt文档。
Python+Qt Quick:一种便捷的桌面软件开发模式_第2张图片
QML文件在Qt Creator中编辑的效果

程序开发

推荐《Qt Quick核心编程》,结合Qt文档,可以解决95%以上的问题,我在这里只谈及一些比较重要的或很难搜到的点(示例代码取自之前开发的次第程序)。

Python+Qt Quick:一种便捷的桌面软件开发模式_第3张图片
《Qt Quick核心编程》

■ Python与QML的结合

这种开发模式不再是通过不断调用库函数来生成、设置界面元素,界面乃至操作层面的响应逻辑全部以ECMAScript的脚本形式存在,99%的代码的都在QML文件,由Python把它驱动起来:

# cidi.py
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine

if __name__ == '__main__':
    app = QGuiApplication([])
    engine = QQmlApplicationEngine()
    engine.load(QUrl('./res/cidi.qml')) #QML文件的相对路径
    app.exec_()

最简单的QML文件示例:

// ./res/cidi.qml
import QtQuick 2.7
import QtQuick.Window 2.0

Window {
    title: qsTr("次第 3.0.0")
    visible: true
}

运行(我把代码文件放在D:\cidi\\目录下):

python d:\cidi\cidi.py

当然我个人喜欢写个批处理放在旁边,每次直接双击就行:

@echo off
python cidi.py
pause

众所周知,Qt的事件处理机制靠信号和槽实现,PyQt中有多种使用方式,我觉得将Python类注册到Qt的做法最清晰、便捷。例如定义一个判断文件路径是否为文件夹的方法(槽),使用注解@pyqtSlot描述参数和返回值的类型:

# cidi.py
from PyQt5.QtCore import QUrl, QObject, pyqtSlot, QFileInfo
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine

class Dealer(QObject):
    @pyqtSlot(str, result=bool)
    def isDir(self, url):
        fileInfo = QFileInfo(url)
        return fileInfo.isDir()

if __name__ == '__main__':
    app = QGuiApplication([])
    qmlRegisterType(Dealer, "cidi.qt.Dealer", 1, 0, "Dealer") #将Dealer注册到Qt
    engine = QQmlApplicationEngine()
    engine.load(QUrl('./res/cidi.qml'))
    app.exec_()
// ./res/cidi.qml
import QtQuick 2.7
import QtQuick.Window 2.0
import cidi.qt.Dealer 1.0 //像模块一样导入

Window {
    title: qsTr("次第 3.0.0")
    visible: true

    //像一般控件一样定义后使用
    Dealer {
        id: dealer
    }

    //可以在任何地方直接调dealer.isDir(pathStr)使用
}

■ 设置程序icon

即程序窗口左上角的小图标。在QGuiApplication实例化语句后添加:

QGuiApplication.setWindowIcon(QIcon("./res/cidi.ico"))

icon制作推荐Axialis IconWorkshop,试过诸多工具,唯有Axialis能生成256×256的超大图标(此处不需要这么大,但程序发布时需要),但它的试用版只能用一个月,暂时没找到破解版。

发布

需要发布的是Python程序,Qt作为其库被它调用即可。Python的打包工具大抵有py2exe、PyInstaller和cx_Freeze三种,其中py2exe只支持到Python 2.7,PyInstaller支持到3.5但操作起来比较复杂(反正我试了一下没搞定),cx_Freeze支持到3.6且操作便捷,缺点是会把许多没用到的库也打包进来,需要手动筛减,但可能前两者也存在同样的问题。

安装和使用cx_Freeze

到PyPI下载cx_Freeze-5.0.1-cp36-cp36m-win32.whl,安装:

pip3 install D:\cx_Freeze-5.0.1-cp36-cp36m-win32.whl

注意莫把whl文件放在中文路径下,不知为何,pip3似乎不支持。

与其他Python工具不同的是,cx_Freeze装完后,Scripts文件夹下居然没有相应的可执行文件:

只有三个没有后缀的文件

我一脸懵逼,根本不知道怎么用,试了几次才琢磨出来。先切换到Scripts目录:

cd C:\Python\Python36-32\Scripts

使用python cxfreeze -h命令查看cx_Freeze文档:

Python+Qt Quick:一种便捷的桌面软件开发模式_第4张图片

有些选项如目标路径、图标设置一目了然,有些选项不明所以。官网和一些技术博客喜欢介绍编辑一个setup.py文件的使用方法,但我觉得一般使用不需要这么复杂,一句简单的命令足矣:

python cxfreeze --target-dir="d:/cidi/dist" --icon="d:/cidi/res/cidi.ico" --base-name=win32gui D:\cidi\cidi.py
  • --base-name选项指定生成目录。
  • --icon选项用于嵌入图标文件,即最终所得exe文件的图标。
  • --base-name=win32gui选项隐藏Python的控制台黑框,调试时可去掉。

这条命令下去,只见命令行刷刷地滚动,D:\cidi\\目录下分分钟多了个200M左右(吓死人)的dist文件夹,里头内容狗血式的丰富:

Python+Qt Quick:一种便捷的桌面软件开发模式_第5张图片
一堆Python和Qt库,Qt占了大半体积,需要人工甄别哪些是没用的(这一过程并不复杂)。

我的次第程序最终删减到30余M,这一数量级还是可以接受的。

注意事项

  • 也许是PyQt库的bug,生成的文件无法在中文路径下运行,但我们可以通过动态设置PyQt查找模块的路径(原路径可能存在字符编码的问题)来解决这一问题:
engine.setImportPathList([sys.path[0] + "/PyQt5/Qt/qml"]) #engine为QQmlApplicationEngine实例
  • Python 3.6基于VS 2015,部分缺少其库的电脑需要安装「Visual C++ Redistributable for Visual Studio 2015」补丁才能运行我们发布的程序。

  • Python从3.5开始不再支持XP,我们的程序要求系统至少是Vista。同时,所用的PyQt版本可能对显卡提出要求,太老旧的电脑hold不住。一句话,新的技术需要新的环境。

  • 生成的主程序(即可执行程序)在修改文件名后无法正常运行,这个问题有待后续解决。

Python+Qt Quick:一种便捷的桌面软件开发模式_第6张图片
比如我把它命名成「次第.exe」


2017年4月25日、26日 苏州

你可能感兴趣的:(Python+Qt Quick:一种便捷的桌面软件开发模式)