前言

  写文章之前我都喜欢加个前言,说说自己的感受,这次也不例外。
  这篇文章是学习 Python Qt 半年来出的教程,因此教程的质量并不能保证,只是将自己的经验分享给大家。
  Python Qt 图形界面开发需要有一定的编程基础,观看本教程之前要有Python的使用基础。
  因为我本人是 流程TD ,开发环境主要在 Maya 上,因此这套教程主要针对于 Maya 的 开发环境,不过Qt是通用于各个软件平台的,有问题可以相互交流。

什么是Qt

alt

  Qt具体是什么,可以自行网上百度.
  简单地说就是一个跨平台的图形化框架,通过这个框架可以实现跨平台的软件界面。
  跨平台主要指可以在多个平台上运行,最通俗的说法是兼容 Linux、Mac、Windows 这三个最常用的系统。
  Qt曾经由诺基亚公司维护,目前由Digia公司维护,在桌面软件开发上有不可撼动的地位。

为什么使用Qt

  由于Qt可以减少跨平台维护的问题。
  如今很多软件都是利用Qt搭建图形化界面,包括但不限于Houdini、Maya、Nuke等等
  作为插件开发者,掌握Qt的图形化开发可以极大加快开发效率。

Qt开发使用的语言

  Qt这个框架是使用 C++ 代码实现的,在现成的软件中嵌入 C++ 代码是非常不便的。
  而python作为胶水语言、脚本语言,补足了这方面的短板。
  python之所以这么好,原因是底层也是基于 c 语言。

python Qt 框架

  在Qt发展到4.0的时候,PyQt4 框架诞生了,通过python平台调用Qt库,实现了python的图形化界面。
  通过python编写的框架,让代码编写更加明了清晰,调用也更为方便。
  PyQt由于是不完全开源的,Qt的运营商 诺基亚 交涉无果之后,自行开发了完全免费开源的python库PySide。
  由于两个 python 库都是基于 C++ 的 Qt 框架下实现的,因此在使用的API上基本保持一致。
  当然后面 Qt 发展到 5.0 之后,也诞生了 PyQt5 以及 PsSide2 , 框架的使用上也有别于之前的版本。
  由于 PySide 的开源商用免费,如今大多数软件开发都使用了PySide 最为 Python 平台的选择。

Qt.py 多版本Qt兼容

  由于在 Qt4.0 到 Qt5.0 的API差异,以及 python 平台下两个库的使用,导致 Qt 代码的兼容非常麻烦。
  为了解决兼容问题,github上有开源的 Qt.py 脚本,通过这个脚本就可以用 Qt5.0 使用方式兼容 Qt4.0 的写法,以及 PyQt 和 PySide 的不同平台的差异问题。
  不过使用这个兼容脚本会导致 代码编辑器(IDE) 的代码补全失效 (:з」∠)


Python Qt 在CG行业的运用

插件开发

  由于Qt跨平台的特性,以及Python的胶水语言的便利,太多CG软件支持Qt的开发。
  正如上文提到的 Houdini、Maya、Nuke 都支持通过 Python 的 Qt 库来编写图形化界面。
  那么Qt编写界面的优势在哪里呢?
  下面我用maya原生的MEL代码编写界面来对比 PyQt 的实现效果

MEL & cmds VS PySide 图形界面开发

  下面我来写出一个 hello world 标题的窗口界面举例。

1
2
3
4
5
6
7
proc printHelloWorld(){
print "hello,World";
}
string $window = `window "使用 MEL 编写窗口"`;
columnLayout;
button -c "printHelloWorld()" "hello,world";
showWindow $window;

  如果你不喜欢MEL语言,也可以将其转换为 maya cmds 命令库来实现

1
2
3
4
5
6
7
8
from maya import cmds
def printHelloWorld(e):
print "hello,World"

window = cmds.window("使用 maya cmds 编写窗口")
cmds.columnLayout()
cmds.button("hello,world",c=printHelloWorld)
cmds.showWindow(window)

  下面是使用 Qt 的方式来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtCore import *
def printHelloWorld(self):
print "hello,world"

window = QWidget()
window.setWindowTitle(u"欢迎使用 PySide2 编写窗口")
button = QPushButton("hello,world")
button.clicked.connect(printHelloWorld)
layout = QHBoxLayout()
layout.addWidget(button)
window.setLayout(layout)
window.show()

  除了上述的实现方案之外,也可以使用类来封装,这种写法更加优雅一些

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtCore import *
class Window(QWidget):
def __init__(self):
super(Window,self).__init__()
self.setWindowTitle(u"欢迎使用 PySide2类 编写窗口")
self.button = QPushButton("hello,world")
self.button.clicked.connect(self.printHelloWorld)
self.layout = QHBoxLayout()
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.show()
def printHelloWorld(self):
print "hello,world"
a = Window()

  看完上面的代码实现之后,会有种感觉,使用PySide的实现要写更多的代码,岂不是更加麻烦吗?
  其实 MEL 实现的图形化界面也是调用了 Qt 框架,只是在调用上进行封装,因此用更少的代码就可以实现而已。
  那在开发的过程中到底孰优孰劣呢?
  在CG行业中应该选择哪一个进行图形界面开发呢?
  其实 MEL 或者 maya cmds 命令实现要比 PySide 简单很多,如果只是写一个简单的图形化界面的话,用原生实现就已经足够了。
  最直观的典型就是 advance skeleton 这款绑定插件了,如此复杂的界面其实全部都是用 MEL 实现的。
  有兴趣的可以研究它的 MEL 源码,3万多行代码是真的牛逼。
alt
  那 Python Qt 的框架优势在哪里呢?

  • QtDesigner 组件拖拽式开发
  • 组件封装扩展
  • 多重事件响应触发
  • qss 自定义样式支持
  • 自定义响应信号

  如果不需要上述这些特性的话,那么完全可以依靠原生来编写界面
  那么上述五个特性到底是个啥,就留到后面的教程娓娓道来吧。