最近因为开发编辑器用到了Qt这个跨平台GUI框架,实际开发时使用了PyQt。PyQt结合了Qt强大的跨平台功能以及Python易于编写的特性。这里从实际使用层面介绍下这两周来的PyQt使用心得。
使用Qt Designer
GUI编程最烦人的一点在于界面代码的编写。直接在代码中进行界面编程特别繁琐且难以维护。如果将界面实现与逻辑代码分离,无疑能极大改善编程体验。PyQt安装之后可以找到Qt Designer这个工具,在Qt Designer中可以进行界面编辑,其导出的文件可以被代码直接使用。
将Qt Designer导出文件转化为Python代码
pyuic4 -o window.py window.ui
在实际开发的时候并不一定需要做如上转化,这个转化的好处在于可以通过生成的代码来帮助熟悉控件的使用。
Python代码中直接读取.ui文件
在实际使用中,直接在代码中加载.ui文件是更合适的选择。如此,则界面与逻辑就可以进行一定程度的分离,避免在代码中陷入界面编写的细节。
# -*- encoding:utf-8 -*-
from PyQt4 import QtGui, uic
class CustomDialog(QtGui.QDialog):
def __init__(self, cb):
super(InputIdDialog, self).__init__()
uic.loadUi("ui/custom_dialog.ui", self)
self.cb = cb
self.setWindowTitle(u"对话框")
事件响应与处理
除了界面实现之外,事件处理机制也是GUI框架必需的组成部分。在PyQt中,事件通过"signal"进行触发处理。这里不探究其内部实现,从使用层面来看与其它GUI框架无大不同。
button.clicked.connect(handle_clicked)
def handle_clicked():
pass
上述代码片段描述的是针对按钮的点击响应处理,PyQt里将事件与响应函数通过connect方法绑定到一起。不同控件定义了多种不同signal,这些预定义的signal会在控件执行操作时进行触发。
自定义signal
PyQt支持自定义signal,其使用方法也极为简单,这里借用个例子,
class Communicate(QtCore.QObject):
closeApp = QtCore.pyqtSignal()
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.c = Communicate()
self.c.closeApp.connect(self.close)
self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Emit signal')
self.show()
def mousePressEvent(self, event):
self.c.closeApp.emit()
继承自QObject的类都可以自定义signal,通过emit进行触发、connect进行绑定。上述代码中还可以看到,可以进一步重载底层的mousePressEvent之类函数来自定义操作行为处理逻辑。
控件与布局
明白了上述两个大问题后,剩下的就是具体的细节了,比如PyQt中默认的控件与布局管理有哪些。结合Qt Designer可以快速浏览支持的控件布局,以及它们的各项属性。
遇到的坑
signal的绑定操作需要在主线程中执行,在其它线程中执行操作貌似不会生效。