前言

  上期视频我们介绍了 Qt 开发,并且简单对比了原生开发和Qt开发的不同之处。
  Qt开发似乎需要写更多的代码,需要更复杂的操作。
  其实不慌,当你学习了 QtDesigner 之后,你就会开始觉得原生开发是多么地不人性化了:-)

什么是 QtDesigner

  QtDesigner是由官方推出并维护的,图形化界面制作窗口的工具。
  如果你接触过 Android 开发 以及 Web前端的 Bootstrap 可视化,都可以感受到这种拖拽开发的快速之处。
  当然目前我觉得图形化拖拽做得最好的还是QtDsigner。
Android Studio 图形化界面开发
Bootstrap 可视化开发

安装Qt Designer

  安装Qt Designer 的方法有很多

  • 安装官方提供的 Qt Creator 开发软件
  • 安装任意 Qt Python包
  • 安装Maya自带Qt Designer

Qt Creator

  Qt Creator是一个IDE,是针对Qt优化的 C++ 开发平台,里面内置了许多Qt开发相关的工具,Qt Designer 就在其中。
  具体安装流程参考网上的文章

Qt Python 包

  安装任意Qt Python 包
  只要安装好 Python 环境,可以打开cmd控制台,通过 pip 安装相关的 Python 包
  另外需要注意的是,如果安装旧版本的 PyQt4 ,已经无法直接通过 pip install 安装,需要手动到对应的网站下载 wheel 进行安装。参考
  当你安装好之后,你可以在 Python 的 site-packages 目录下找到 PyQt4 文件夹
PyQt4 文件夹
  打开目录可以找到 designer.exe 程序
designer.exe 程序

Maya 自带 Qt Designer

  打开 maya 的安装路径
  可以在 bin 目录下找到 designer.exe 程序
designer.exe 程序
  maya中的 designer.exe 程序打开可能会报错
报错
  网上可以找到解决方案 参考

  还有一个方法就是将maya安装目录下的 qt-plugins 中的 platforms 拷贝到 bin 目录下

platform

初始 Qt Designer

  启动 Qt Designer 之后可以看到如下画面
Qt Designer 初始界面
  我们可以选择 widget 创建出窗口
创建 Widget 窗口
  下面就可以拖拽左侧的组件到窗口上
创建排列UI
  注:按住 ctrl 拖拽可以快速复制组件
布局按钮
  窗口上方的这些按钮可以改变窗口的布局,也可以从左侧拖拽相关的布局到窗口上。
  Qt 自带的布局我上期教程也有提及过,最常用的有

  • QHBoxLayout - 横向布局
  • QVBoxLayout - 竖向布局
  • QGridLayout - 网格布局

  通过这些布局就可以让组件等分排布,从而减少UI的凌乱感
  横向布局 就是将布局内部的组件 横向等分排列
  竖向布局 也顾名思义
  
  网格布局 则需要给定网格的位置对网格进行等分,也可以让组件占用多个网格,或者空出多余的网格。
  通过网格布局可以排列出下面这种形态组件状态。
网格布局

  在 Qt Designer 的右侧有属性编辑器以及对象查看器的大纲视图
  属性编辑器可以编辑UI的属性,不过很多时候,是用代码来动态修改这些属性。
XML文件
  通常情况下,objectName比较重要,因为后面代码调用的时候会通过 objectName 的属性来调用。
  当你创建完成 UI 之后,就可以 ctrl+s 保存当前编辑的文件
  Qt Designer 会输出一个后缀为 ui 的文件
  如果你用文本编辑器打开 ui 文件,你会发现其实它是个XML文件
XML文件
  因此当你熟悉了它XML输出的格式也可以通过魔改XML里面的内容来生成出特殊的组件文件。

在 maya 中调用 ui 文件

  默认情况下 ui 文件只是 XML 配置而已,是无法直接使用的。
  不过也有多种情况让ui文件运行起来

  • 通过 python Qt 框架下的 pyuic5 或者 pyside2-uic 将 ui 文件编译为 python 文件
  • 导入uic相关的python模块,通过读取 ui 文件的内容动态编译python代码
  • 直接用 maya 内置的命令编译 ui 文件

编译 ui 文件

  在maya安装目录的bin目录下有 pyside2-uic 程序 - 命令行的使用方法
pyside2-uic 程序

  这个程序要运行起来需要添加 .exe 后缀,而且在我的电脑上运行会出现报错。
pyside2-uic编译程序
  注: bin 目录下还有 uic.exe 程序是可用的,只不过编译出来的文件是 C++ 代码 (:з」∠)


  后来我发现这个程序之所以不可用,是因为它压根就不是 exe 程序。
  将程序放到编辑器中可以看到它是一个 python 脚本来的 (:з」∠)

pyside2-uic编译程序

  因此我们不需要对文件加 exe 后缀,而是要通过 python 来调用这个脚本。
  不过外部的python可能会因为 PySide 的相关依赖而报错,因此最为稳妥的方式是使用 mayapy.exe 来调用这个脚本

pyside2-uic编译程序


  因此如果maya内置uic编译器不可用的话,可以通过安装相关的 Python Qt 库,可以在相关路径下找到编译程序
PyQt 包下的 编译程序
pyside2-uic编译程序
  通过命令行调用这个程序后面加上 -h 可以显示出使用方法
pyside2-uic 程序 帮助

1
2
pyside2-uic C:\Users\Administrator\Desktop\img\test.ui -o C:\Users\Administrator\Desktop\img\test_ui.py

  基本写法就是: 程序名 ui文件 -o 输出的python文件
  这样就可以将 ui 文件 编译为 python 文件,不过需要注意的是 PyQt的编译 maya 需要 改为 PySide 的库进行导入
  编译好的文件可以通过继承的方法来调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 编译好的 ui 文件 导入其中的类(类名和UI文件当中的最外层的组件的objectName一致)
from test_ui import Ui_Form
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtCore import *

class window(Ui_Form,QWidget):
def __init__(self):
# 执行 QWidget 的 __init__
super(window,self).__init__()
# 从 Ui_Form 继承的方法,可以直接将ui生成出来
self.setupUi(self)
self.setWindowTitle(u"用 pyside2-uic 程序编译python 继承出来的窗口")
self.show()

win = window()

代码执行效果

直接用代码编译

  此处可以参考我以前看教程写的文章

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
import sys
import pyside2uic
import xml.etree.ElementTree as xml
from cStringIO import StringIO
def loadUiType(uiFile):
# 通过XML模块读取ui文件
parsed = xml.parse(uiFile)
# 获取Qt相关的组件名
widget_class = parsed.find('widget').get('class')
# 获取类名
form_class = parsed.find('class').text

with open(uiFile, 'r') as f:
o = StringIO()
frame = {}
# 通过 pyside2uic 编译 ui 文件
pyside2uic.compileUi(f, o, indent=0)
# o.getvalue() 这里的数据就是 UI 文件编译成python的代码,通过 exec 执行字符串实现动态执行 python 代码
pyc = compile(o.getvalue(), '<string>', 'exec')
exec pyc in frame

# form_class 就是ui文件编译出来的类名
form_class = frame['Ui_%s'%form_class]
# base_class 就是Qt的窗口组件 eval 获取出 变量
base_class = eval('%s'%widget_class)

return form_class, base_class

UI_PATH = r"C:\Users\Administrator\Desktop\test.ui"
form_class , base_class = loadUiType(UI_PATH)
# 这里的继承其实和上面编译好的 ui 文件的代码是一样的
class Interface(base_class,form_class):
def __init__(self):
super(Interface,self).__init__()
self.setupUi(self)
self.setWindowTitle(u"用 pyside2uic 编译出来的窗口")
self.show()
ui = Interface()

代码执行效果

  通过这个函数可以直接将ui文件在编译到内存当中,这样每次修改ui文件就不需要再额外用 exe 工具进行编译了
  当然缺点就是没有了ui编译好的python文件,组件的自动代码提示也就没有了,所以开发的时候还需要对着 Qt Designer 的名字,有点麻烦。

  额外补充一下,上述的方案只适用于 PySide ,如果使用PyQt实现的话,代码会简略很多。

1
2
3
4
5
from PyQt4 import uic
UI_PATH = r"C:\Users\Administrator\Desktop\test.ui"

# 读取 UI 文件的窗口类型和窗口名
form_class , base_class = uic.loadUiType(UI_PATH)

  其实后来我才我发现 PySide 也有快速加载 ui 文件的方法

1
2
3
4
from PySide2.QtUiTools import QUiLoader
UI_PATH = r"C:\Users\Administrator\Desktop\test.ui"
# 直接返回组件实例
widget = QUiLoader(UI_PATH)

maya 内置命令编译UI文件

  maya的 mel 有 loadUi 命令,可以直接将ui文件路径读取 生成出 maya 的窗口

1
2
3
4
string $dialog1 = `loadUI -f "C:\\Users\\Administrator\\Desktop\\test.ui"`;
window -e -title "通过 mel 编译的 ui 文件" $dialog1;
showWindow $dialog1;

代码执行效果

总结

  Qt designer 的使用并不复杂,虽然Qt Designer 支持信号槽等比较高级的开发内容,但是由于很难通过 XML 来实现所需要的触发效果,因此难当大任。
  我目前使用 Qt designer 也是为了快速创建出UI界面,毕竟手打界面的效率还是比较低的,特别是还要考虑各种固定组件的布局位置。
  后续的组件触发大都是放在 python 代码当中完成。
  如果想要更进一步了解 Qt Designer 的开发,可以参考B站上的教程