Maya2017以及Nuke10的PySide都升级到PySide2了,之前PySide1的大量代码都无法在新软件上使用,这主要是由于PySide2不仅调整了模块位置,还增删了一系列模块,下面我分享一段Shotgun的兼容代码,把模块位置调整回来:

from __future__ import with_statement

import os
import functools
import imp
import subprocess
import sys
import webbrowser class PySide2Patcher(object):
_core_to_qtgui = set([
"QAbstractProxyModel",
"QItemSelection",
"QItemSelectionModel",
"QItemSelectionRange",
"QSortFilterProxyModel",
"QStringListModel"
]) @classmethod
def _move_attributes(cls, dst, src, names):
"""
Moves a list of attributes from one package to another. :param names: Names of the attributes to move.
"""
for name in names:
if not hasattr(dst, name):
setattr(dst, name, getattr(src, name)) @classmethod
def _patch_QTextCodec(cls, QtCore):
"""
Patches in QTextCodec. :param QTextCodec: The QTextCodec class.
"""
original_QTextCodec = QtCore.QTextCodec class QTextCodec(original_QTextCodec):
@staticmethod
def setCodecForCStrings(codec):
pass QtCore.QTextCodec = QTextCodec @classmethod
def _fix_QCoreApplication_api(cls, wrapper_class, original_class): wrapper_class.CodecForTr = 0
wrapper_class.UnicodeUTF8 = 1
wrapper_class.DefaultCodec = wrapper_class.CodecForTr @staticmethod
def translate(context, source_text, disambiguation=None, encoding=None, n=None): if n is not None:
return original_class.translate(context, source_text, disambiguation, n)
else:
return original_class.translate(context, source_text, disambiguation) wrapper_class.translate = translate @classmethod
def _patch_QCoreApplication(cls, QtCore): original_QCoreApplication = QtCore.QCoreApplication class QCoreApplication(original_QCoreApplication):
pass
cls._fix_QCoreApplication_api(QCoreApplication, original_QCoreApplication)
QtCore.QCoreApplication = QCoreApplication @classmethod
def _patch_QApplication(cls, QtGui): original_QApplication = QtGui.QApplication class QApplication(original_QApplication):
def __init__(self, *args):
original_QApplication.__init__(self, *args)
QtGui.qApp = self @staticmethod
def palette(widget=None): return original_QApplication.palette(widget) cls._fix_QCoreApplication_api(QApplication, original_QApplication) QtGui.QApplication = QApplication @classmethod
def _patch_QAbstractItemView(cls, QtGui): original_QAbstractItemView = QtGui.QAbstractItemView class QAbstractItemView(original_QAbstractItemView):
def __init__(self, *args):
original_QAbstractItemView.__init__(self, *args) if hasattr(self, "dataChanged"):
original_dataChanged = self.dataChanged def dataChanged(tl, br, roles=None):
original_dataChanged(tl, br)
self.dataChanged = lambda tl, br, roles: dataChanged(tl, br) QtGui.QAbstractItemView = QAbstractItemView @classmethod
def _patch_QStandardItemModel(cls, QtGui): original_QStandardItemModel = QtGui.QStandardItemModel class SignalWrapper(object):
def __init__(self, signal):
self._signal = signal def emit(self, tl, br):
self._signal.emit(tl, br, []) def __getattr__(self, name):
return getattr(self._signal, name) class QStandardItemModel(original_QStandardItemModel):
def __init__(self, *args):
original_QStandardItemModel.__init__(self, *args)
self.dataChanged = SignalWrapper(self.dataChanged) QtGui.QStandardItemModel = QStandardItemModel @classmethod
def _patch_QMessageBox(cls, QtGui): button_list = [
QtGui.QMessageBox.Ok,
QtGui.QMessageBox.Open,
QtGui.QMessageBox.Save,
QtGui.QMessageBox.Cancel,
QtGui.QMessageBox.Close,
QtGui.QMessageBox.Discard,
QtGui.QMessageBox.Apply,
QtGui.QMessageBox.Reset,
QtGui.QMessageBox.RestoreDefaults,
QtGui.QMessageBox.Help,
QtGui.QMessageBox.SaveAll,
QtGui.QMessageBox.Yes,
QtGui.QMessageBox.YesAll,
QtGui.QMessageBox.YesToAll,
QtGui.QMessageBox.No,
QtGui.QMessageBox.NoAll,
QtGui.QMessageBox.NoToAll,
QtGui.QMessageBox.Abort,
QtGui.QMessageBox.Retry,
QtGui.QMessageBox.Ignore
] def _method_factory(icon, original_method): def patch(parent, title, text, buttons=QtGui.QMessageBox.Ok, defaultButton=QtGui.QMessageBox.NoButton): msg_box = QtGui.QMessageBox(parent)
msg_box.setWindowTitle(title)
msg_box.setText(text)
msg_box.setIcon(icon)
for button in button_list:
if button & buttons:
msg_box.addButton(button)
msg_box.setDefaultButton(defaultButton)
msg_box.exec_()
return msg_box.standardButton(msg_box.clickedButton()) functools.update_wrapper(patch, original_method) return staticmethod(patch) original_QMessageBox = QtGui.QMessageBox class QMessageBox(original_QMessageBox): critical = _method_factory(QtGui.QMessageBox.Critical, QtGui.QMessageBox.critical)
information = _method_factory(QtGui.QMessageBox.Information, QtGui.QMessageBox.information)
question = _method_factory(QtGui.QMessageBox.Question, QtGui.QMessageBox.question)
warning = _method_factory(QtGui.QMessageBox.Warning, QtGui.QMessageBox.warning) QtGui.QMessageBox = QMessageBox @classmethod
def _patch_QDesktopServices(cls, QtGui, QtCore): if hasattr(QtGui, "QDesktopServices"):
return class QDesktopServices(object): @classmethod
def openUrl(cls, url):
if not isinstance(url, QtCore.QUrl):
url = QtCore.QUrl(url) if url.isLocalFile():
url = url.toLocalFile().encode("utf-8") if sys.platform == "darwin":
return subprocess.call(["open", url]) == 0
elif sys.platform == "win32":
os.startfile(url)
return os.path.exists(url)
elif sys.platform.startswith("linux"):
return subprocess.call(["xdg-open", url]) == 0
else:
raise ValueError("Unknown platform: %s" % sys.platform)
else:
try:
return webbrowser.open_new_tab(url.toString().encode("utf-8"))
except:
return False @classmethod
def displayName(cls, type):
cls.__not_implemented_error(cls.displayName) @classmethod
def storageLocation(cls, type):
cls.__not_implemented_error(cls.storageLocation) @classmethod
def setUrlHandler(cls, scheme, receiver, method_name=None):
cls.__not_implemented_error(cls.setUrlHandler) @classmethod
def unsetUrlHandler(cls, scheme):
cls.__not_implemented_error(cls.unsetUrlHandler) @classmethod
def __not_implemented_error(cls, method):
raise NotImplementedError(
"PySide2 and Toolkit don't support 'QDesktopServices.%s' yet. Please contact %s" %
(method.__func__, 'asdf@qq.com')
) QtGui.QDesktopServices = QDesktopServices @classmethod
def patch(cls, QtCore, QtGui, QtWidgets, PySide2): qt_core_shim = imp.new_module("PySide.QtCore")
qt_gui_shim = imp.new_module("PySide.QtGui") cls._move_attributes(qt_gui_shim, QtWidgets, dir(QtWidgets))
cls._move_attributes(qt_gui_shim, QtGui, dir(QtGui)) cls._move_attributes(qt_gui_shim, QtCore, cls._core_to_qtgui)
cls._move_attributes(qt_core_shim, QtCore, set(dir(QtCore)) - cls._core_to_qtgui) cls._patch_QTextCodec(qt_core_shim)
cls._patch_QCoreApplication(qt_core_shim)
cls._patch_QApplication(qt_gui_shim)
cls._patch_QAbstractItemView(qt_gui_shim)
cls._patch_QStandardItemModel(qt_gui_shim)
cls._patch_QMessageBox(qt_gui_shim)
cls._patch_QDesktopServices(qt_gui_shim, qt_core_shim) return qt_core_shim, qt_gui_shim import PySide2
from PySide2 import QtCore, QtGui, QtWidgets def _import_module_by_name(parent_module_name, module_name): module = None
try:
module = __import__(parent_module_name, globals(), locals(), [module_name])
module = getattr(module, module_name)
except Exception as e:
pass
return module QtCore, QtGui = PySide2Patcher.patch(QtCore, QtGui, QtWidgets, PySide2)
QtNetwork = _import_module_by_name("PySide2", "QtNetwork")
QtWebKit = _import_module_by_name("PySide2.QtWebKitWidgets", "QtWebKit") ###########################################################################################
# Test In Maya2017
widonw = QtGui.QWidget()
widonw.show()

我们把这段代码复制到Maya2017中的Scirpt Editor中执行,可以看到,QtGui.QWidget()成功运行。说明当前PySide2中的模块已经按照PySide1的方式整理好了,兼容问题搞定,你可以沿用PySide1的调用方式来使用PySide2。

当然你也可以采用Autodesk官方提供的解决方案:

try:
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2 import __version__
from shiboken2 import wrapInstance
except ImportError:
from PySide.QtCore import *
from PySide.QtGui import *
from PySide import __version__
from shiboken import wrapInstance

但这种方案有个弊端,所有控件都没有缺少引入模块的标识,代码并不适合阅读。读者各取所长吧。

PySide2兼容PySide1的补丁代码的更多相关文章

  1. 加入收藏夹的js代码(求兼容chrome浏览器的代码)

    从网上找了加入收藏夹的js代码,但不兼容chrome,不知道有没有兼容chrome的相关代码,希望有知道的告诉一下,谢谢! 代码如下 $("#id").click(function ...

  2. Babel+vscode实现APICloud开发中兼容ES6及以上代码

    本文出自APICloud官方论坛, 感谢论坛版主 penghuoyan 的分享.   使用APICloud开发时,考虑到兼容问题一直使用ES5开发,时间越久感觉越落后,整理了一个兼容ES6的开发环境, ...

  3. 关于hr标签兼容个浏览器的代码

    hr标签,相信大家都能熟悉,我们一般用它来产生横线的效果.我们可以对它定义“颜色”.“高度”.“宽度”.“边框”等样式. 在此只讨论“颜色”和“边框”对于不同版本浏览器的兼容性. 颜色: 火狐.IE7 ...

  4. Javascript substr方法在某些浏览器下行为出现BUG的补丁代码

    主要思路是使用兼容性和稳定性都保持一致的substring方法重写/覆盖substr /** * String.substr() bug fix * @param start * @param len ...

  5. 解决IE浏览器兼容问题的一行代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 兼容 数组 api map代码

    if(!("map" in Array.prototype)) Array.prototype.map=function(fun){ for(var i=0,arr=[]; i&l ...

  7. Ajax的完整兼容各种浏览器版本代码

    <script type="text/javascript"> function createAjax(){ var request=false; //window对象 ...

  8. 【IE兼容性】代码中多语言样式+IE不兼容解决

    一.代码中样式根据不同语言对IE做不兼容解决 二.代码逻辑: 1. 后台返回语言信息: result.addObject("language",getLocaleStr());   ...

  9. 使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization)

    使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization) 前言: 这是 qt for python 的语言国际化,基于 UI 的,python 也有 ...

随机推荐

  1. 机器学习笔记(四)Logistic回归模型实现

     一.Logistic回归实现 (一)特征值较少的情况 1. 实验数据 吴恩达<机器学习>第二课时作业提供数据1.判断一个学生能否被一个大学录取,给出的数据集为学生两门课的成绩和是否被录取 ...

  2. Java复数的加乘除运算

    //主要是对零的处理,有什么不对的地方欢迎批评指正,一起进步class complex{ double a,b; public String toString() { return("实部: ...

  3. 利用隐藏 iframe 下载文件

    在开发项目中遇到问题:下载文件后台报错,下载文件的页面会出现空白或异常信息,需要解决. 解决方法:利用隐藏iframe下载文件 3:对于a标签,采用target属性方法 <a target=&q ...

  4. day 15递归 匿名函数

    三元表达式 目的是简化书写 局限性:三元表达式智能简化仅有两个分支的if判断,而且这个判断无论是否成立都必须要返回值 res = True if age >=18 else False 递归: ...

  5. 作为程序员你不知道中国互联网300强你就OUT了!

    很多程序员们工作一段时间之后,都想跳槽到综合实力更强的公司以获取高薪资或者接触到前沿的技术,但是哪些行业值得我们投入大量的时间,哪些公司属于我们行业中的佼佼者呢, 那么小编给您分析下2018年中国互联 ...

  6. redis客户端(三)

    redis客户端 一.>redis自带的客户端 启动 启动客户端命令:[root@ming bin]# ./redis-cli -h xxx.xxx.xx.xxx-p 6379 注意: -h:指 ...

  7. 《Java编程思想》读书笔记-赋值操作符

    在最底层,Java中的数据是通过使用操作符来操作的.接下来我们逐一认识一些操作符. 怎么运用操作符 操作符接受一个或多个参数,并生成一个新值. 基本操作符 赋值操作符 符号:= 作用:取右边的值,把它 ...

  8. Simple circos code

    According to the tutorials (http://circos.ca/documentation/tutorials/), to draw a graph using circos ...

  9. Visual C++ 6.0中关于for的简单问题

      在这个循环当中,要先执行①,再执行②,再执行④,再执行③,如果还满足②的话就再执行②,再依次执行.当③不满足②时,就执行printf语句. 并且在这个循环当中,①只执行一次.

  10. tab切换 原生js

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...