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 也有 ...
随机推荐
- Linux一些常用操作命令
1.创建一个等同于root管理员的用户 useradd -u 0 -o -g root -G root -d /home/username username usermod -u 0 -o ...
- C++中的tolower()函数与toupper()函数
https://blog.csdn.net/weixin_41053564/article/details/81349353 在C++语言中tolower()函数是把字符串都转化为小写字母 toupp ...
- PHP协程入门详解
概念 咱们知道多进程和多线程是实现并发的有效方式.但多进程的上下文切换资源开销太大:多线程开销相比要小很多,也是现在主流的做法,但其的控制权在内核,从而使用户(程序员)失去了对代码的控制,而且线程的上 ...
- 使用VB6读取数据库资源并发送邮件(原创)
Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection ...
- python学习第三次记录
python学习第三次记录 python中常用的数据类型: 整数(int) ,字符串(str),布尔值(bool),列表(list),元组(tuple),字典(dict),集合(set). int.数 ...
- ABP vue+asp.net core yarn serve报 Cannot find module 'typescript/package.json错误
abp的前端在node install 安装完成了相关的依赖包,直接yarn serve运行相关服务的时候报"Cannot find module 'typescript/package.j ...
- Delphi编程之好用的三方控件
Delphi的强大与其庞大的组件库息息相关,目前的XE10.1版本已自带FastReport和GDI+等,下面我们来看一下几个非常强大且实用的组件库 一.DevExpress套件 Dev包含Grid. ...
- Python小白 哆唻a梦 用turtle绘图
点击观看视频 # -*- coding: utf-8 -*- """ Created on Sat Nov 10 22:02:32 2018 @author: 10029 ...
- Linux查看服务器配置
服务器型号 [root@txs ~]# dmidecode|grep "System Information" -A9|egrep "Manufacturer|Produ ...
- SpringBoot的启动流程分析(1)
通过分析我们可以找到 org.springframework.boot.SpringApplication 中如下, public static ConfigurableApplicationCont ...