PyQt5 环境配置和Python GUI编程介绍

来源:互联网 发布:王安忆长恨歌知乎 编辑:程序博客网 时间:2024/05/01 17:54

最近用学习Python编程,动手做了一个聊天软件的项目。
界面部分用的是PyQt5,然而PyQt5和Qt5刚刚推出不久,专业书更新不及时,网络资料又比较混乱,甚至连PyQt5的Python API参考也只是链接到了Qt5的C++代码上。
摸索了一阵子之后终于做出来了,这里跟大家分享一些经验和资料,少走弯路。

为什么使用PyQt?

Python的GUI工具有很多,除了作为缺省标准的Tkinter,主流的都有GUI库几乎都有Python绑定,PyQt/PySide,wxPython,PyGTK等等,甚至可以用Jython调用Java类库来做GUI开发,IronPython调用.Net来开发。
而PyQt因为基于Qt,具有功能强大、跨平台、所见即所得、简洁的特性,且适合快速开发,可以说是目前Python GUI的上上之选。

如何配置PyQt?(Windows和Linux待更新)

OS X

为了使PyQt5正常工作,需要提前安装一些依赖项。
1、首先从Qt官网下载最新的Qt 5.5.0 for Mac并安装,注意版本号和平台的选择。
下载链接:http://www.qt.io/zh-hans/download-open-source/#section-2
2、下载最新的sip-4.16.8,这个需要我们自己编译安装,方法:
解压缩,打开终端并cd到文件夹目录,依次输入python configure.pymakesudo make install
3、下载最新的PyQt-5.4.2,同样需要我们手动编译安装,过程稍微复杂些:
安装pyqt5需要上面的sip,还需要qmake(做界面的时候,我们的PyQt将输入的Python代码转换成Qt的C++代码,qmake实际上是Qt的编译器)。

  • 解压缩,使用终端cd到文件目录
  • 这里要将Qt5添加到环境变量~/.bash_profile,方便PyQt引用。
  • 编译安装,在终端敲入命令(注意将/gzxultra替换成你的用户名,参照我的命令以你实际文件夹的位置进行修改):
$python configure.py -q /Users/gzxultra/Qt/5.5.0/clang_64/bin/qmake -d /Library/Python/2.7/site-packages/ --sip /System/Library/Frameworks/Python.framework/Versions/2.7/bin/sipmakesudo make install

界面开发需要哪些步骤?

图形界面的开发基本是一个顺序的流程,一般如下:
1、在Qt Designer组织控件;
2、用布局管理器框定控件的具体位置;
3、设置控件的tab顺序和控件之间的伙伴关系;
4、绑定信号和信号槽;
5、保存为.ui设计文件;
6、用pyuic5命令将.ui设计文件转换成.py的Python模块;
7、在主程序导入ui模块创建ui类并实现所有的信号槽。

实际开发

这里以聊天软件登陆窗口为例:
1、在Qt Designer中新建空白Widget窗体
新建空白Widget窗体
2、将窗体拖拉到合适的大小
3、摆放控件:
我们创建两个标签(Label)、两个行编辑器(Line Edit)和两个按钮(PushButton)。对于这里的每一项,可先从Qt设计师的窗口部件工具箱中拖拽其名字或者图表并将其放到窗体中的大概位置。现在不必为怎么摆放这些部件花费太多的时间,稍后我们使用Qt的布局管理器,可以把这些部件摆放好。
摆放控件
4、配置空间、窗体的属性:
使用Qt设计师的属性编辑器(图2中右中部分)可以设置每一个窗口部件的属性,这里需要设置TextLable的text(显示文字)和objectName(规范下对象名称,方便后续编程),设置主窗体的名称和对象名,设置LoginButton的enabled为false(稍后配置信号和信号槽,使得当密码栏不为空时才能按下登陆按钮),等等。
设置属性
5、编辑伙伴:
单击“编辑→编辑伙伴件”,将用户名和userNameEdit绑定,将密码和passwordEdit绑定。
进入编辑伙伴模式
编辑伙伴
6、使用布局管理器规范控件的摆放:
我们将所有的部件设置在“栅格布局(GridLayout)”中:按住Command或Ctrl键,选择所有的部件,然后点击“窗体栅格布局”,将它们设置在一个网格的布局中,部件自动摆放好了:
布局管理
7、设置Tab顺序:
单击“编辑编辑tab顺序”,在每一个可以接受焦点的窗口部件上,都会出现一个带蓝色矩形的数字。按照你所希望的接受焦点的顺序单击每一个窗口的部件,然后单击“编辑→编辑窗口部件”,离开Tab键顺序模式。
设置Tab顺序
8、绑定信号和信号槽:
考虑信号和信号槽的编写和绑定是界面设计的重点和难点。
首先要添加槽函数,槽函数是某个窗体或控件在接收到特定信号时,执行既定操作(函数)
在登陆界面上,我们有两个自定义的函数,login()和enableLoginButton(),在Qt Designer里声明他,然后在Python代码中实现它。
在窗体上右键单击,如果要声明其他部件的槽函数,就在该部件上右键单击),在弹出的右键菜单中选择“改变信号/槽”,弹出编辑“Form信号和槽”的对话框,在槽(slots)部分,单击加号,添加这两个函数。
信号和槽
接下来绑定信号和槽。
在“编辑信号/槽”模式下,单击passwordEdit行编辑输入框并按着鼠标左键,将红色的箭头拖动到窗体的空白处(因为槽函数enableLoginButton是属于主窗体的),释放鼠标按键,其余的槽函数和信号绑定类似。操作的结果如图,注意在顶部的信号/槽编辑器里检查下是否连接正确。
绑定信号和槽
9、预览:
这样我们在Qt Designer的工作就告一段落了,保存为untitled.ui文件,在窗体->预览中看看效果是否满意,可以随时修改。
预览
10、将.ui转换成.py界面模块
在终端里cd到ui文件目录,输入命令转换文件:

pyuic5 -o ui_widget.py untitled.ui

这样就生成了ui_widget.py的界面类文件,注意这个类只是描述了各个窗体、空间的属性、关系,以及信号和信号草的绑定,还需要在主程序中导入并继续实现。
11、界面类的初始化和自定义槽函数的实现
enableLoginButton()函数在接收到密码栏有输入(即textChange)的信号后使loginButton可以点按。
login()则在用户按下登陆按钮后将用户名和密码组织成消息,发送给已经建立连接的服务器并验证。如果匹配则进入聊天状态,如果不匹配弹出错误警告。
这里给出代码样例
(因为是从项目冲抽取的片段,并不能直接运行,读者需领会程序框架)

from ui_widget import Ui_LoginDlgfrom PyQt5 import QtCore, QtGui, QtWidgetsclass IM_loginDlgImpl(QtWidgets.QDialog, Ui_LoginDlg):    """QtGui.QWidget和界面设计时选择的类型一致"""    def __init__(self, parent=None):        QtWidgets.QWidget.__init__(self, parent)        self.setupUi(self) # Ui_Form.setupUi        #self.pushButton.clicked.connect(self.myPrint)   #槽函数不用加括号    #def myPrint(self):                                #定义槽        #self.hide()    def enableLoginButton(self, text):        self.loginButton.setEnabled(True)    def login(self):        userName = self.userNameEdit.text()        password = self.passwordEdit.text()        client.setLocalANDPort('127.0.0.1', 8808)        client.setUsrANDPwd(userName, password)        client.setToUsr('12073128')        authentication = client.check_info()        if authentication == True:            his.setup(userName)            self.hide()            ex2.show()            # client.receiveMessage()            thread.start_new_thread(client.receiveMessage, ())        else:            ex3.show()

主程序:

if __name__ == '__main__':    app = QtWidgets.QApplication(sys.argv)    ex = IM_loginDlgImpl()    ex2 = IM_FormImpl()    ex3 = IM_messageBoxImpl()    ex4 = IM_NewsBoxImpl()    ex5 = IM_HistoryImpl()    client = ClientMessage()    his = MessageHistory()    ex.show()    sys.exit(app.exec_())
0 0