欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

程序员文章站 2022-04-28 11:13:26
wxPython框架虽然成熟稳定,但是相对最近更火的PyQt框架来说,还是显得古老了一些,控件风格不符合现代审美观,因此痞子衡决定学习一下PyQt的用法,感受下PyQt做出来的界面效果到底如何。根据wxPython学习经验,当然首先要从PyQt的可视化GUI构建工具Qt Designer开始下手,因... ......

  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是pyqt gui构建工具qt designer

  痞子衡开博客至今已有好几年,一直以嵌入式开发相关主题的文章为主线,偶尔穿插一些其他技术或工具的介绍,前段时间因为要做一个跟恩智浦mcu启动相关的上位机工具 nxp-mcubootutility,网上搜索对比了几个python下的gui框架,最终选择了wxpython这个成熟稳定的gui库,从而接触到wxformbuilder这个配套wxpython使用的gui构建工具。苦于网上关于该构建工具的中文资料不多,所以根据自己使用经验写了一篇 极易上手的可视化wxpython gui构建工具(wxformbuilder),没想到该篇博客很受欢迎,居然目前是痞子衡博客里阅读量最高的一篇博客,而且也是搜索 wxformbuilder 关键字出来的中文结果排名第二位的链接,真是万万没想到。

  wxpython框架虽然成熟稳定,但是相对最近更火的pyqt框架来说,还是显得古老了一些,控件风格不符合现代审美观,因此痞子衡决定学习一下pyqt的用法,感受下pyqt做出来的界面效果到底如何。根据wxpython学习经验,当然首先要从pyqt的可视化gui构建工具qt designer开始下手,因此便有了本篇博客。

一、qt designer工具背景

  qt designer从名字上来看显然就是久负盛名的跨平台gui库qt的配套设计工具。qt库本身是c++语言实现的;riverbank公司用python语言对qt做了一层封装,封装后便成了python版gui库pyqt(目前最新的版本是pyqt5);下面是这两个gui库的官方主页:

  • qt项目官方网站:
  • pyqt项目官方主页:

  qt的各种ui控件功能均是通过class来实现的,这个链接 列出了qt里的所有class。pyqt5其用法基本与qt一致,这个链接 https://www.riverbankcomputing.com/static/docs/pyqt5/module_index.html#ref-module-index 列出了pyqt5里所有的modules,其中用于设计界面最常用的便是 qtwidgets 模块。

  在qt官网的tools下面可以看到所有qt相关的工具,在ui design tools下面可以找到qt designer,可见qt designer是用于设计gui界面的工具之一。由于痞子衡介绍的pyqt5下的gui构建工具,因此本文的qt designer并不是直接在qt官网下载安装的,具体安装方法详见下一章节。

痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

二、qt designer快速上手

  使用qt designer去设计gui界面可以不用掌握pyqt5里的各个控件class的具体用法,你只需要在qt designer软件里添加这些控件即可,下面痞子衡将简介qt designer的用法:

2.1软件安装

  简单了解pyqt5的module和class便可以开始设计gui界面,首先得安装qt designer,在安装完python3之后(痞子衡安装的是python 3.6),借助\python36\scripts\下的pip.exe工具来分别安装pyqt5和qt designer,命令见如下主页:

  安装完成之后打开\python36\lib\site-packages\pyqt5_tools\designer.exe,这便是qt designer。

2.2软件界面

  打开qt designer可见到如下界面,界面主要分为四大区:项目区、控件区、编辑区、属性区。软件使用起来非常简单,就是在【控件区】里点击添加需要的控件,这些控件的效果会在【编辑区】里实时显示,并在【属性区】这些控件的属性,【项目区】用于显示控件间的层级关系。

痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

2.3基础布局

  让我们开始创建一个gui的基础框架,基础框架包括:container(局部外围轮廓)、layout(内部控件区)、menubar(顶部菜单栏)、statusbar(底部状态栏)。
  第一步是添加一个container(此处选择常用的frame),这是gui的轮廓基础,有了frame之后还需要在frame里添加layout(此处选择竖排样式),用于规范后续控件的排列样式。默认gui即有menubar和statusbar。

痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

2.4多种控件

  基础布局搞定之后,接下来便是在layout里添加控件,pyqt5支持的控件非常丰富,其中比较常用的是如下几个:各种button(按钮)、label(静态显示文本框)、text edit(输入输出文本框)、check box(选中框)、各种slider(滑动条)等。由于前面痞子衡选择的是verticallayout,因此你会看到控件们都是竖着排的。

痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

2.5控件属性

  添加了所有控件之后,下一步便是分别设置控件的属性,进一步调整控件。痞子衡以push button属性为例,痞子衡勾选了如下3项比较重要的属性设置,分别是objectname(button在后续python代码的对象名,一般需要按其功能修改,修改后使得代码阅读/修改起来更直观)、geometry(设置button的尺寸与位置,如果是放在layout里,则受限于layout不可设置)、text(button在gui里显示的标签名,此处是pushbutton,也需要按其功能修改,方便用户使用软件)。

痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

2.6保存为xml代码(工程文件)

  当gui界面布局全部完成之后,需选择file->save as保存为.ui文件,该文件既是qt designer的工程文件也是最终生成的gui xml代码文件,痞子衡保存在了my_win.ui文件里。

痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

2.7转换成python代码

  虽然保存的my_win.ui文件里是可以直接在python代码里被加载使用的,但是更好的办法是直接将.ui文件转换成相应的.py文件。需要借助 \python36\scripts\pyuic5.exe工具,命令如下:

pyuic5 - o my_win.py my_win.ui

  转换成功后,让我们打开my_win.py文件,可以简单看一下这个my_win.py里的内容,代码里首先import了pyqt5相关库,并定义了名为ui_mainwindow的class,这个class主要包含两个函数setupui()和retranslateui()。setupui()里初始化了各个控件成员self.xx,这与我们在qt designer里添加控件是对应的。

# -*- coding: utf-8 -*-

# form implementation generated from reading ui file '.\my_win.ui'
#
# created by: pyqt5 ui code generator 5.11.3
#
# warning! all changes made in this file will be lost!

from pyqt5 import qtcore, qtgui, qtwidgets

class ui_mainwindow(object):
    def setupui(self, mainwindow):
        mainwindow.setobjectname("mainwindow")
        mainwindow.resize(603, 448)
        self.centralwidget = qtwidgets.qwidget(mainwindow)
        self.centralwidget.setobjectname("centralwidget")
        self.frame = qtwidgets.qframe(self.centralwidget)
        self.frame.setgeometry(qtcore.qrect(100, 80, 361, 211))
        self.frame.setframeshape(qtwidgets.qframe.styledpanel)
        self.frame.setframeshadow(qtwidgets.qframe.raised)
        self.frame.setobjectname("frame")
        self.verticallayoutwidget = qtwidgets.qwidget(self.frame)
        self.verticallayoutwidget.setgeometry(qtcore.qrect(30, 20, 160, 172))
        self.verticallayoutwidget.setobjectname("verticallayoutwidget")
        self.verticallayout = qtwidgets.qvboxlayout(self.verticallayoutwidget)
        self.verticallayout.setcontentsmargins(0, 0, 0, 0)
        self.verticallayout.setobjectname("verticallayout")
        self.pushbutton = qtwidgets.qpushbutton(self.verticallayoutwidget)
        self.pushbutton.setenabled(true)
        self.pushbutton.setobjectname("pushbutton")
        self.verticallayout.addwidget(self.pushbutton)
        self.label = qtwidgets.qlabel(self.verticallayoutwidget)
        self.label.setobjectname("label")
        self.verticallayout.addwidget(self.label)
        self.textedit = qtwidgets.qtextedit(self.verticallayoutwidget)
        self.textedit.setobjectname("textedit")
        self.verticallayout.addwidget(self.textedit)
        self.checkbox = qtwidgets.qcheckbox(self.verticallayoutwidget)
        self.checkbox.setobjectname("checkbox")
        self.verticallayout.addwidget(self.checkbox)
        self.horizontalslider = qtwidgets.qslider(self.verticallayoutwidget)
        self.horizontalslider.setorientation(qtcore.qt.horizontal)
        self.horizontalslider.setobjectname("horizontalslider")
        self.verticallayout.addwidget(self.horizontalslider)
        mainwindow.setcentralwidget(self.centralwidget)
        self.menubar = qtwidgets.qmenubar(mainwindow)
        self.menubar.setgeometry(qtcore.qrect(0, 0, 603, 21))
        self.menubar.setobjectname("menubar")
        mainwindow.setmenubar(self.menubar)
        self.statusbar = qtwidgets.qstatusbar(mainwindow)
        self.statusbar.setobjectname("statusbar")
        mainwindow.setstatusbar(self.statusbar)

        self.retranslateui(mainwindow)
        qtcore.qmetaobject.connectslotsbyname(mainwindow)

    def retranslateui(self, mainwindow):
        _translate = qtcore.qcoreapplication.translate
        mainwindow.setwindowtitle(_translate("mainwindow", "mainwindow"))
        self.pushbutton.settext(_translate("mainwindow", "pushbutton"))
        self.label.settext(_translate("mainwindow", "textlabel"))
        self.checkbox.settext(_translate("mainwindow", "checkbox"))

三、使用qt designer生成的代码

  前面已经使用qt designer生成gui界面类ui_mainwindow并保存在my_win.py文件中,此时需要创建一个主函数文件去调用ui_mainwindow,下面是痞子衡创建的main_win.py中的代码:

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow
# 导入my_win.py中内容
from my_win import *

# 创建mainwin类并传入ui_mainwindow
class mainwin(qmainwindow, ui_mainwindow):
    def __init__(self, parent=none):
        super(mainwin, self).__init__(parent)
        self.setupui(self)

if __name__ == '__main__':
    # 下面是使用pyqt5的固定用法
    app = qapplication(sys.argv)
    main_win = mainwin()
    main_win.show()
    sys.exit(app.exec_())

3.1触发事件与响应

  有了button,我们肯定希望其能与一个响应函数相联系起来,此处痞子衡定义了showmessage()函数,并且将showmessage()与pushbutton绑定起来,点击button便会执行一次这个showmessage()函数。代码如下:

class mainwin(qmainwindow, ui_mainwindow):
    def __init__(self, parent=none):
        super(mainwin, self).__init__(parent)
        self.setupui(self)
        # 将响应函数绑定到指定button
        self.pushbutton.clicked.connect(self.showmessage)

    # button响应函数
    def showmessage(self):
        self.textedit.settext('hello world')

  最后让我们测试一下这个gui软件,在命令行下运行main_win.py

ps d:\my_git_repo\> python .\main_win.py

痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

  至此,pyqt5 gui构建工具qt designer痞子衡便介绍完毕了,掌声在哪里~~~

参考资料

  1. 使用pyqt来编写第一个python gui程序
  2. pyqt5速成教程-2 qt designer介绍与入门