PyQT是知名跨平台框架QT的python绑定;用它来做些小程序既可以利用QT的跨平台性又能利用python强大的表达能力,从而取得事半功倍的效果。下边是使用它开发一个小程序过程中的学习小笔记。
UI界面设计
QT Designer
使用过VC做过MFC开发的,对所见即所得(WYSIWYG)的工具不会陌生,QT Designer就是类似的一个。其设计就是将代码和UI空间分开,控件布局和对象名称都可以在里边设置,每个空间都有对应的属性表,可以针对很多控件属性做默认定制。最后生成对应的python代码。
生成代码
生成的代码主要集中于控件显示的部分,事件处理的部分虽然也可以产生,但是仅适用于自定义子类的对象,因为在slot里边没法很方便的为已有的某个UI对象添加新的方法,只能靠子类化的办法来修改类的预定义slot,远不如在代码中自己写来的快捷方便。
每个界面的设计最终会生成一个.ui后缀的XML文件,使用如下的Makefile规则可以做方便的转换:
1 2 |
|
尽量少混杂动态控制逻辑到UI设计中
对于某些需要多步骤协作完成某个特性的控件,在Designer里边修改一部分属性,然后再在代码中完成另一部分是不方便的。譬如设计一个弹出的对话框,如果想设置它为Modal
的,那么最好还是在代码里边,在创建的时候设置要来得方便和清晰的多;否则除了问题,排查起来就比较麻烦。
逻辑实现和控制
简单控件和逻辑事件
简单的控件使用,有过MFC开发经验的自然容易照搬来做,基本都很像。唯一有些不同的是,在python里边,绑定事件处理的方式灵活了很多,不但可以用QObject
类的connect
方法来做,也可以直接在signal对象上来直接绑,而且绑定的参数可以是任何的callable
,譬如:
1 2 3 4 |
|
对于显示空间,QT支持对它的显示特性做CSS定制,但是在Designer里边必须指定允许扩展stylesheet,然后可以在对于的stylesheet里边设置样式;对应的编辑框里边还提供颜色选择和渐变选择等图形工具。如果需要实现动态的样式变化,则需要在代码逻辑中完成。
一些复杂的控件设计
菜单和状态栏
可以在Designer中选择是否需要菜单栏和状态栏。如果没有设置,那么在生成的代码里边调用menuBar()
或者statusBar()
这样的函数也会创建一个新的,但是对应的显示属性就必须完全自己代码设置了。
表格控件和数据操作
QT的表格控件可以映射到二位数组,其实现建立在它自己的模型/视图框架之上,可参考QAbstractItemView
类的文档。简单说来,是需要提供一个数据模型类,在该数据模型类里边封装底层的实际数据,并且至少实现如下方法:
1. rowCount()
提供表格的行数
1. columnCount()
提供表格的列数据个数
1. headerData()
提供表格表头数据显示或者修改
以上的方法可以提供一个只读的表控件。如果需要支持可编辑表格(已经显示的数据部分),则需要以下方法:
1. setData()
完成数据设置
1. flags()
需要返回一个可编辑的标记
如果需要支持记录的增加/删除/修改,则需要:
1. insertRows()
完成实际数据的增加操作,并在开始的时候调用beginInsertRows()
,操作完毕的时候调用 endInsertRows()
1. removeRows()
完成数据的删除操作,开始操作之前调用beginRemoveRows()
,完毕之后调用endRemoveRows()
1. insertColumns()
完成列数据增加操作,数据操作需包在beginInsertColumns()
和endInsertColumns()
之间
1. removeColumns()
列删除,操作需要被beginRemoveColumns()
和endRemoveColumns()
之间
需要对表格列进行排序,则需要自己实现sort()
函数,根据传入的列编号和排序方法,对实际数据进行排序,并且在排序之前,发送layoutAboutToBeChanged()
通知信号,完成排序之后,发送layoutChanged()
信号。
当然也可以自己写函数完成修改操作,但是如果牵扯到记录行列的改动,则必须保证对于的begin
和end
方法被正确调用,否则界面的数据可能无法正确刷新。
QModelIndex
大部分的数据操作都携带一个Index参数,该参数负责定位对应的具体数据,并且精确定位到某一个单元格,可以用切row()
和column()
方法得到其行/列编号。也可以通过给定的行/列号构造一个Index;但是该参数并不能直接定位行数据。在跟踪用户选择的时候,选择的是一整行数据的话,返回的选择列表包含所有的单元格;如果想获取行,则需要对行号做如下变换:
1
|
|
上述的代码利用set的特性将多余的行自动删除,并且再转换回list的时候已经是排序过的。
Selection Model
如果想跟踪用户的选择并获取通知,则需要绑定对于的selectionModel对象的相关信号。具体的定义可参考QItemSelectionModel
的 singla/slot部分。对应的定位方法仍然是依据单元格。
如果对于的model数据发生变化(譬如调用了setModel()
),那么对于的selectionModel会发生变化。
如何利用QT的文档
QT的官方文档都是针对C++的,对于Python绑定并没有提供专门的文档,因此 stackoverflow 上也有很多的提问;总结起来,可以有下边几种办法 :
- 使用QT的官方文档 – 本地装一个,用浏览器打开其页面就是,很方便的展开看类结构和每个类的概要文档
- PySide网站的文档, 提供各个平台的安装包
- 使用bpython工具,手工导入包,然后可以看每个类方法的文档