以前Python写出来的脚本都是靠命令行执行,输入要是复杂点就得靠加参数,甚至加配置文件来搞定,自己用下还行,给别人用的时候总是不太方便,就一直想找个好用的图形界面库。
有试过Python内置的Tkinter,部署倒是挺简单,不需要额外安装库,但是开发效率还是不够高,而且需要手写不少界面相关的重复代码,用起来不太方便。
最近开始尝试第三方的界面库,几经权衡,最终在PyGTK、wxPython、PyQT中选择了PyQT,试了一下,确实很不错,下面就介绍一下PyQT的使用方法。
1 介绍
PyQT以QT为基础,跨平台(可以运行在Windows、Linux/Unix、MacOS等操作系统上),同时PyQT的界面可以直接用QT Designer做出来,可以很容易移植到其它语言上(C++、C#、Java、Perl等)。
2 例子
为了更好了了解PyQT,先写一段简单的示例代码,例子中通过点击按钮,来改变文本框所显示的内容,具体代码含义直接通过注释说明了。
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
# 自定义的窗口类
class TestWindow(QtGui.QWidget):
# 窗口初始化
def __init__(self, parent = None):
super(TestWindow, self).__init__(parent)
self.setWindowTitle(u'胡桃夹子')
# 创建按钮
self.pushButton = QtGui.QPushButton(u'测试按钮')
# 创建文本框
self.textEdit = QtGui.QTextEdit()
# 创建垂直布局
layout = QtGui.QVBoxLayout()
# 将控件添加到布局中
layout.addWidget(self.textEdit)
layout.addWidget(self.pushButton)
# 设置窗口布局
self.setLayout(layout)
# 设置按钮单击动作
self.pushButton.clicked.connect(self.sayHello)
# 按钮动作处理
def sayHello(self):
self.textEdit.setText('Hello World!')
# 程序主入口
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
mainWindow = TestWindow()
mainWindow.show()
sys.exit(app.exec_())
源文件下载:链接
运行效果如下图,点击按钮后,文本框中会显示Hello World!
字符串:
3 设计界面
了解了PyQT之后,设计界面的工作就可以交给QT设计器来完成,不再需要手写界面代码,最大限度的提高界面开发速度。下面通过QT设计器的方式再完成一次上面例子中的功能。
在QT设计器中,新建一个Dialog
类型的窗体,然后向窗体中分别加入Vertical Layout
、Push Button
和Text Edit
三个控件,并界面摆成下图的样子:
还可以通过设置各控件的属性来修改界面显示的文字、效果等,此处不过多叙述,下面将设计好的界面保存为qt_designer_example.ui
文件,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>280</width>
<height>240</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>258</width>
<height>221</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
源文件下载:链接
可以看出,QT设计器所保存的界面是XML文件格式的,事实上,QT设计器所生成的界面可以很自由的移植到不同语言中,甚至不需要太多额外的适配工作,非常方便。
4 生成代码
有了QT界面,下一步就需要用pyuic
这个工具来将QT界面转换为Python代码(基于PyQT库),转换命令如下:
pyuic4 -x -o qt_designer_example.py qt_designer_example.ui
其中-o qt_designer_example.py
用来标识输出文件名;这里需要特别说明的是-x
参数,该参数表示是否生成额外的测试代码来显示窗口,建议加上该参数,这样的话可以方便直接调试运行。
下面是通过pyuic
工具生成的Python代码:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'qt_designer_example.ui'
#
# Created: Wed Dec 18 22:52:55 2013
# by: PyQt4 UI code generator 4.10.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.setWindowModality(QtCore.Qt.NonModal)
Dialog.resize(279, 262)
self.verticalLayoutWidget = QtGui.QWidget(Dialog)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 20, 258, 221))
self.verticalLayoutWidget.setObjectName(_fromUtf8("verticalLayoutWidget"))
self.verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setMargin(0)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.textEdit = QtGui.QTextEdit(self.verticalLayoutWidget)
self.textEdit.setObjectName(_fromUtf8("textEdit"))
self.verticalLayout.addWidget(self.textEdit)
self.pushButton = QtGui.QPushButton(self.verticalLayoutWidget)
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.verticalLayout.addWidget(self.pushButton)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
self.pushButton.setText(_translate("Dialog", "PushButton", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Dialog = QtGui.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
源文件下载:链接
5 处理事件
QT采用的是Signal
(信号)和Slot
(槽)的机制来处理事件,Signal负责发送消息来触发事件动作,Slot负责接收消息并进行相应的事件处理(在PyQT中,Signal和Slot可以是任何类型)。
有两种方式可以连接Signal和Slot:
方法一:传统QT的连接方式
self.connect(self.sender, SIGNAL("sndSignal(int)"), self.receiver, SLOT("rcvSlot(int)"))
方法二:适用于Python的连接方式
self.sndSignal.connect(self.receiver.rcvSlot)
本例中我们在Ui_Dialog
类的setupUi
函数中增加Signal/Slot的连接,然后再增加一个sayHello
的事件(Slot)处理函数,先来看下方法一的连接方式:
class Ui_Dialog(object):
def setupUi(self, Dialog):
... ...
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.sayHello)
def sayHello(self):
self.textEdit.setText('Hello World!')
下面是方法二的连接方式:
class Ui_Dialog(object):
def setupUi(self, Dialog):
... ...
self.pushButton.clicked.connect(self.sayHello)
def sayHello(self):
self.textEdit.setText('Hello World!')
可以看出方法二的连接方式使用更简单,也更符合Python的编程风格。
6 后记
完成上述步骤后,就可以运行Python脚本了,运行后界面功能和开头中的例子基本相同,只不过这个是用QT设计器辅助完成的,相比手写界面代码来说,效率高了不少。
Comments