PyQt中如何结合Qt设计师进行开发
2013-03-08 PyQt4 Designer 3条评论
Qt设计师是Qt的所见即所得的界面设计工具,通过拖拉方式设计界面,但它并不能产生任何代码。
Qt设计师使用.ui后缀的XML文件来存储界面内容。通过pyuic4命令可以编译成.py文件,.py文件的内容就和我们手写界面的类似。
当然直接使用.ui文件也是可以的,但是有两个问题,一个是效率不高,需要在运行时做动态转换创建界面;二是不方便打包发布。这里只讲最佳实践,不讲这种方式,感兴趣的可以自己研究。我后面会写文章讲解。
下面通过一个例子,讲述如何创建界面,并编译,以及如何使用信号和槽。该例子上有一个QLabel和一个QPushButton。点击按钮,修改标签的文字为“Hello PyQt4”。
环境:
- OS X 10.8.2
- Python2.7.3
- PyQt4.9.4
创建界面
打开Qt设计师,在templates/forms中选择Widget,点击【创建】。进入设计状态,从窗口部件盒中拖出两个Vertical Spacer、一个Label,一个Push Button。如图所示:
在空白处点击右键,选择垂直布局。
双击按钮修改文字为"Say Hello",选中对象在属性编辑器中修改属性:
- Label的objectName为lHello
- Push Button的objectName属性为pbHello。
完成后的界面如下:
打开widget.ui,你会发现是个XML文件。
转换界面文件为python代码
通过pyuic4命令转换代码,把widget.ui转换成ui_widget.py文件。
- $ pyuic4 -o ui_widget.py widget.ui
转换后代码如下:
- from PyQt4 import QtCore, QtGui
-
- try:
- _fromUtf8 = QtCore.QString.fromUtf8
- except AttributeError:
- _fromUtf8 = lambda s: s
-
- class Ui_Form(object):
- def setupUi(self, Form):
- Form.setObjectName(_fromUtf8("Form"))
- Form.resize(400, 300)
- self.verticalLayout = QtGui.QVBoxLayout(Form)
- self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
- spacerItem = QtGui.QSpacerItem(20, 98, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
- self.verticalLayout.addItem(spacerItem)
- self.lHello = QtGui.QLabel(Form)
- self.lHello.setObjectName(_fromUtf8("lHello"))
- self.verticalLayout.addWidget(self.lHello)
- self.pbHello = QtGui.QPushButton(Form)
- self.pbHello.setObjectName(_fromUtf8("pbHello"))
- self.verticalLayout.addWidget(self.pbHello)
- spacerItem1 = QtGui.QSpacerItem(20, 98, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
- self.verticalLayout.addItem(spacerItem1)
-
- self.retranslateUi(Form)
- QtCore.QMetaObject.connectSlotsByName(Form)
-
- def retranslateUi(self, Form):
- Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
- self.lHello.setText(QtGui.QApplication.translate("Form", "TextLabel", None, QtGui.QApplication.UnicodeUTF8))
- self.pbHello.setText(QtGui.QApplication.translate("Form", "Say Hello", None, QtGui.QApplication.UnicodeUTF8))
注意到代码中self.lHello和self.pbHello变量,他们的名字是和我们前面界面设计的objectName是一一对应的。
注意
不要把业务代码写在ui_widget.py文件中,下次使用pyuic4命令的时候将会覆盖该文件,你所做的一切工作将白费。
使用转换后的界面代码
这里只介绍使用Python的多重继承方式。这种方式有个好处是代码编写方便,而且可以通过self. + objectName的方式来调用界面组件。
- # -*- coding: utf-8 -*-
- from PyQt4 import QtGui
- from ui_widget import Ui_Form
-
- class Widget(QtGui.QWidget, Ui_Form):
- """QtGui.QWidget和界面设计时选择的类型一致"""
- def __init__(self, parent=None):
- QtGui.QWidget.__init__(self, parent)
- self.setupUi(self) # Ui_Form.setupUi
-
-
- if __name__ == '__main__':
- import sys
- app = QtGui.QApplication(sys.argv)
- widget = Widget()
- widget.show()
- sys.exit(app.exec_())
处理按钮点击事件
PyQt支持使用QtCore.pyqtSignature()装饰器来连接信号和槽,不需要通过手工连接。具体方法名为on_objectName_信号,代码如下:
- # -*- coding: utf-8 -*-
- from PyQt4 import QtGui, QtCore
- from ui_widget import Ui_Form
-
- class Widget(QtGui.QWidget, Ui_Form):
- """QtGui.QWidget和界面设计时选择的类型一致"""
- def __init__(self, parent=None):
- QtGui.QWidget.__init__(self, parent)
- self.setupUi(self) # Ui_Form.setupUi
-
- @QtCore.pyqtSignature("")
- def on_pbHello_clicked(self):
- """pbHello和界面设计时的objectName一致"""
- self.lHello.setText('Hello PyQt4') # lHello和界面设计的objectName一致
-
- if __name__ == '__main__':
- import sys
- app = QtGui.QApplication(sys.argv)
- widget = Widget()
- widget.show()
- sys.exit(app.exec_())
完整代码下载:hellopyqt.zip