PySide2兼容PySide1的补丁代码
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的补丁代码的更多相关文章
- 加入收藏夹的js代码(求兼容chrome浏览器的代码)
从网上找了加入收藏夹的js代码,但不兼容chrome,不知道有没有兼容chrome的相关代码,希望有知道的告诉一下,谢谢! 代码如下 $("#id").click(function ...
- Babel+vscode实现APICloud开发中兼容ES6及以上代码
本文出自APICloud官方论坛, 感谢论坛版主 penghuoyan 的分享. 使用APICloud开发时,考虑到兼容问题一直使用ES5开发,时间越久感觉越落后,整理了一个兼容ES6的开发环境, ...
- 关于hr标签兼容个浏览器的代码
hr标签,相信大家都能熟悉,我们一般用它来产生横线的效果.我们可以对它定义“颜色”.“高度”.“宽度”.“边框”等样式. 在此只讨论“颜色”和“边框”对于不同版本浏览器的兼容性. 颜色: 火狐.IE7 ...
- Javascript substr方法在某些浏览器下行为出现BUG的补丁代码
主要思路是使用兼容性和稳定性都保持一致的substring方法重写/覆盖substr /** * String.substr() bug fix * @param start * @param len ...
- 解决IE浏览器兼容问题的一行代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 兼容 数组 api map代码
if(!("map" in Array.prototype)) Array.prototype.map=function(fun){ for(var i=0,arr=[]; i&l ...
- Ajax的完整兼容各种浏览器版本代码
<script type="text/javascript"> function createAjax(){ var request=false; //window对象 ...
- 【IE兼容性】代码中多语言样式+IE不兼容解决
一.代码中样式根据不同语言对IE做不兼容解决 二.代码逻辑: 1. 后台返回语言信息: result.addObject("language",getLocaleStr()); ...
- 使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization)
使用 PySide2 开发 Maya 插件系列三:qt语言国际化(internationalization) 前言: 这是 qt for python 的语言国际化,基于 UI 的,python 也有 ...
随机推荐
- python中__name__
1.在运行程序时一般会写 if __name__ == "__main__" 当一个py文件被程序当做模块导入时,python会将文件中的代码执行一遍,如果我们在py文件中写了一些 ...
- Labview多列列表框
前面板创建多列列表框 如何写入数据: 右键 创建属性节点 项名 创建属性节点 项符号 创造自定义项符号: 右键 创建调用节点 自定义项符号 设置为自定义符号 然后添加索引号 利用图片与声音 ...
- Tiny6410 裸机开发--裸机点亮LED
环境搭建 由于我不喜欢使用虚拟机,双系统无法同时烧程序.最近才折腾好Windows10下编译和下载程序,使用的是韦东山做的easy open jtag,资料十分齐全,之前使用jlink搭建环境碰到了一 ...
- Java中8种常见的排序方法
排序方法的演示1)插入排序(直接插入排序.希尔排序)2)交换排序(冒泡排序.快速排序)3)选择排序(直接选择排序.堆排序)4)归并排序5)分配排序(基数排序)所需辅助空间最多:归并排序所需辅助空间最少 ...
- select默认显示
select默认显示第一个option,但大部分需求都是显示一个请选择,点击后在显示option的内容. 就像上图一样 但如果正常写的话会是像下面这样显示 请选择也会显示在下拉款里面,这样就很不友好 ...
- How to Animate UILabel textColor Properties
How to Animate UILabel Properties UILabel properties cannot be easy animated due to some various rea ...
- 浅谈MVC中的service层(转)
概述 mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面. mvc模式是web开发中的基础模式,采用的是分层 ...
- maven各个属性参数详解
<project xmlns="http://maven.apache.org/POM/4.0.0 " xmlns:xsi="http://www.w3.org/2 ...
- Python3 与 Python2 的不同
1. Python3中的字典,删除了has_key(key)的方法. Python2: if result.has_key(middle_s) != None result[middle_s] = 1 ...
- MyBatis-Spring开发记录贴(新手)
初学MyBatis-Spring,发个帖子记录一下自己的学习历程,先写个自己的编程步骤. 1.先进行数据库设计. 2.根据所设计的数据,写出相应的POJO,并写出setter和getter方法. 3. ...