Qt5 开发入门

Python 与 Qt 搭配为开发 GUI 提供了极大的便利。本教程提供了 Qt5(PyQt5 与 PySide2,它们的差异见 PySide2 与 Pyqt5 的区别) 的使用手册[1]。更多学习资料见 Qt for Python

为了兼容 PyQt5 与 PySide2 代码,在 Github 放置 xinetzone / xinet 包用于 Qt5 的开发。

该库提供 pip 支持:

pip install xinet

后续内容将以此模块进行 Qt 的开发。

1 Qt 模块简介[2]

在 Python 中将 Qt 划分为三大类模块:基础模块(QtCore, QtGui, QtWidgets)、功能模块、工具模块。下面依次介绍这些模块。

1.1 通用基础模块

  • QtCore:这个是 Qt5 中的其他模块使用到的核心非图形类。这个模块就像是建造房屋的地基和钢筋,为健壮的图形界面程序提供核心且强大的功能支持,提供了诸如线程(QThread、QThreadPool)、动画(QAbstractAnimation)、事件响应(Signal、Slot、QEvent)、输入/输出对象(QSettings、QFileinfo)等功能。一个使用 Qt5 编写的图形界面程序可以不使用 QtCore 模块,但是一个 Qt5 编写的强大图形界面程序,肯定会使用到 QtCore 模块。
  • QtGui:这个是 Qt5 中图形用户界面组件的基类。其提供了用于图形窗口集成、图形事件处理、2D图形图像、字体和文本的子类。有诸如图形拖放(QDrag、QDropEvent)、图像显示(QBitmap、QImage)、字体定义(QFont)、颜色定义(QColor)、绘笔(QPen)等等的子类,类似于建造房屋时的墙面修砌。
  • QtWidgets:这个是 Qt5 中扩展了 QtGui 模块的控件模块,所谓控件模块,就是其提供了大量的控件及其布局类。这就相当于房子里面客厅、厨房、阳台、卧室,以及其中的各种家具、摆件、电器、设备等等。我们在图形界面编程过程中会使用到大量的 QtWidget 中的子类,图形界面程序中的窗口、按钮、输入框、文本框、选择框、布局等等都是使用它的子类。如同建造房子,我们没有地基(QtCore)、不用水泥砌墙(QtGui),也能用木板和树叶(QtWidget)搭建出一个简易的小屋出来。

注意:我们知道,原生的 Qt 使用的是 C++ 语言进行图形界面的开发,从 Qt4.7 开始,Qt 中引入了一种新的图形界面开发语言——QML 作为原生 QT 开发语言 C++ 的替代品,同时其构建了一套名为 QtQuick 的类库,用于使用自定义图形界面来构建高度动态的图形界面应用程序。

1.2 功能模块

多媒体功能:

  • QtMultimedia:一个多媒体模块,提供对音频、视频、无线电广播和相机功能的支持。
  • QtMultimediaWidgets:一个用于实现多媒体功能的控件模块,提供了设计视频和摄像头额外的控件支持,其扩展了 QtMultimediaQtWidget 模块的功能。

还有:

  • QtNetwork:一个用于实现网络编程的模块,使得在 Qt 图形界面中进行网络编程变得更加方便;这些类通过使网络编程更加容易和可移植,来简化 TCP / IP和 UDP 客户端和服务器的编码。
  • QtSQL:一个用于在 Qt 中使用 SQL 对数据库进行操作的模块。
  • QtTest:一个用于对 Qt 图形界面程序进行单元测试的模块。
  • QtNfc:这个模块提供了对近场通信(NFC)硬件进行访问的支持。
  • QtWebEngine:这个模块借助开源的 Chromium 浏览器项目,在图形界面应用程序中嵌入 Web 浏览功能。
  • QtWebSocket:这个模块为图形界面程序提供了 WebSocket 通信的功能。
  • QtSvg:这个模块提供了用于显示 SVG 文件内容的相关功能。

1.3 工具模块

Qt 的工具模块主要是为了方便开发人员对图形界面程序进行设计和开发,其提供了 Qt 设计师(QtDesigner)这个图形化的程序设计工具,能够便捷地利用鼠标拖拽来快速绘制程序的界面和基础的事件响应。

更多模块介绍见:PyQt5 系统化学习: 架构简介

2 创建简单的窗口

  • QtWidgets.QWidget 类是所有用户界面对象的基类。窗口部件是用户界面的一个基本单元:它从窗口系统接收鼠标、键盘和其它事件,并且在屏幕上绘制自己。每一个窗口部件都是矩形的,并且它们按Z轴顺序排列。一个窗口部件可以被它的父窗口部件或者它前面的窗口部件盖住一部分。
  • QtWidgets.QMainWindow 类提供一个有菜单条、锚接窗口(例如工具条)和一个状态条的主应用程序窗口。主窗口通常用在提供一个大的中央窗口部件(例如文本编辑或者绘制画布)以及周围 菜单、工具条和一个状态条。QMainWindow常常被继承,因为这使得封装中央部件、菜单和工具条以及窗口状态条变得更容易,当用户点击菜单项或者工具条按钮时,槽会被调用。
  • QtWidgets.QDialog 类是对话框窗口的基类。对话框窗口是主要用于短期任务以及和用户进行简要通讯的顶级窗口。QDialog可以是模态对话框也可以是非模态对话框。QDialog支持扩展性并且可以提供返回值。它们可以有默认按钮。QDialog也可以有一个QSizeGrip在它的右下角,使用setSizeGripEnabled()。

对模块有了大体的了解之后,先来创建一个空白的界面窗口。

from xinet import QtWidgets
import sys
# 实例化一个 QApplication 应用程序,用于初始化 GUI
app = QtWidgets.QApplication([])  
gui = QtWidgets.QMainWindow()  # 实例化一个主窗口
gui.show()  # 显示主窗口
app.exec_()  # 退出 GUI
# 也可利用内置模块sys的exit()方法侦听GUI的退出信号,以便关闭Python程序。
# sys.exit(app.exec_())  # 当GUI产生退出信号时Python程序结束

效果:

对于用 Qt 写的任何一个 GUI 应用,不管这个应用有没有窗口或多少个窗口,有且只有一个 QtWidgets.QApplication 应用程序。QtWidgets.QApplication 管理 GUI 程序的控制流和主要设置。它包含由窗口系统和其他来源处理过和发送过的主事件循环。它也处理应用程序的初始化和收尾工作,并提供对话管理。它还可以对系统和应用的大部分设置项进行设置。

为了让 GUI 启动,需要使用 app.exec_() 启动事件循环(启动应用,直至用户关闭它)。主事件循环从窗口系统接收事件,并将其分派给应用程序小部件。如果没有该方法,那么在运行的时候还没有进入程序的主循环就直接结束了,所以运行的时候窗口会闪退。

QtWidgets.MainWindow() 控件是 Qt 中的一个主窗口框架,其提供了构建应用程序图形用户界面的框架。

为了方便后续功能的开发,在 xinet 中定义函数 run 用于启动 GUI 程序。即上述代码可简写为:

from xinet import QtWidgets
from xinet.run_qt import run

run(QtWidgets.QMainWindow)

为该空白窗口添加菜单栏:

from xinet import QtWidgets
from xinet.run_qt import run


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 添加菜单栏
        file_menu = self.menuBar()  # 实例化一个菜单栏
        # file_menu.setFixedWidth(200)  # 设置菜单栏的宽度
        for name in ["文件", "编辑", "关于"]:
            file_menu.addMenu(name)  # 添加菜单按钮


if __name__ == '__main__':
    run(MainWindow)

效果:

添加工具栏:

from xinet import QtWidgets
from xinet.run_qt import run


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 添加工具栏
        view_toolbar = self.addToolBar("View")
        view_toolbar.addAction("打开")
        view_toolbar.addAction("保存")
        view_toolbar.addAction("撤回")


if __name__ == '__main__':
    run(MainWindow)

效果:

添加状态栏:

from xinet import QtWidgets
from xinet.run_qt import run


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 添加状态栏
        status = self.statusBar()
        status.showMessage("这是一个状态栏消息")


if __name__ == '__main__':
    run(MainWindow)

主窗口中的中央控件用于显示主窗口的基础控件,每一个主窗口都会有一个中央控件,就算其是一个占位符,也必须存在。中央控件通常来说是一个标准的 Qt 窗口小控件,比如 QWidget、QPushbutton等等。

更多精彩参考我的另一篇博文:Qt 手册


  1. 关于 PyQt5 与 PySide2 该学习哪一个的问题,您可自行判断。PyQt5 的资源相对较多,而 PySide2 的 Qt 官方原生支持,它有很大的潜力,且更加 Pythonic。

  2. 房与图形界面编程之道 对 GUI 的剖析很精辟。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352