PySide2 等效于 PyQt5 的 loadUiType() 动态混合 UI 设计
PySide2 equivalent of PyQt5's loadUiType() to dynamically mix in UI designs
TL;DR:我想从其与 PySide2 和 [=55 一起使用的 uic
模块中直接替换 PyQt5 的 loadUiType()
函数=] 3.6+.
我想将 PyQt5 应用程序迁移到 PySide2。我使用的一个常见模式是,我在 Qt Designer 中创建用户界面设计并动态加载生成的 .ui
文件作为混合 class 在 Python 代码中扩展 Qt 小部件,比如主 window 本身:
from PyQt5 import QtWidgets, uic
class Window(QtWidgets.QMainWindow, uic.loadUiType('design.ui')[0]):
def __init__(self):
super().__init__()
self.setupUi(self)
print(self.label.text())
app = QtWidgets.QApplication([])
window = Window()
window.show()
app.exec_()
这意味着我可以放弃在命令行上将 .ui
设计编译为 .py
Python 模块。更重要的是,混合模式允许我在导入小部件的范围内通过 self.name
访问设计中定义的所有 Qt 小部件,其中 name
在 Qt Designer 中如此分配。
为了提供一个可重现的例子,这里有一个最小的 Qt 设计文件与上面的 Python 代码一起使用,其中它被引用为 design.ui
:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="label">
<property name="text">
<string>Hi, Qt.</string>
</property>
</widget>
</widget>
</widget>
</ui>
我想完成同样的事情,但使用 PySide2,并且代码更改尽可能少。问题是,PySide2 不提供 PyQt5 的 uic.loadUiType()
函数的等价物,重要的是,returns the design's form class 用作混合。
有一个相关的问题,"PyQt5 to PySide2, loading UI-Files in different classes", but its premise is that the loaded objects be usable from a separate class, which is not my concern per se. Plus, the (currently) only answer to it is not the solution I am looking for. Other questions and their answers (, ) 确定设计文件 可以 通过 QtUiTools.QUiLoader().load('design.ui')
在 PySide2 中动态加载,但是该方法 returns widget 对象,不是要求的形式 class.
后一种方法,如果不混合导入的 class,将需要我为迁移更改许多代码行,因为它会导致 Python 实例变量的不同对象层次结构.在上面的示例中,self.label
然后必须在整个代码库中重命名为类似 self.ui.label
的内容。
我想要的是 PyQt5 的 loadUiType(design)
函数的直接替换,来自其 uic
模块,该模块与 PySide2 和 Python 3.6+ 一起使用,其中 design
指定.ui
文件的路径。
This answer,从 2013 年开始,完美地证明了这一点,但是对于 PySide(基于 Qt4)和(遗留)Python 2. 我如何使该代码适应 PySide2(基于 Qt5) 运行 在(现代)Python?
以下是 Python 3.6 或更高版本和 PySide2 5.13 或更旧版本(见末尾的注释)的改编版本 above-cited,较早的答案:
from PySide2 import QtWidgets
from pyside2uic import compileUi
from xml.etree import ElementTree
from io import StringIO
def loadUiType(design):
"""
PySide2 equivalent of PyQt5's `uic.loadUiType()` function.
Compiles the given `.ui` design file in-memory and executes the
resulting Python code. Returns form and base class.
"""
parsed_xml = ElementTree.parse(design)
widget_class = parsed_xml.find('widget').get('class')
form_class = parsed_xml.find('class').text
with open(design) as input:
output = StringIO()
compileUi(input, output, indent=0)
source_code = output.getvalue()
syntax_tree = compile(source_code, filename='<string>', mode='exec')
scope = {}
exec(syntax_tree, scope)
form_class = scope[f'Ui_{form_class}']
base_class = eval(f'QtWidgets.{widget_class}')
return (form_class, base_class)
如果与主 Python 模块一起另存为 uic.py
,则只需更改 import
语句即可将问题中的示例从 PyQt5 迁移到 PySide2:
from PySide2 import QtWidgets
import uic
在 Windows 10(通过 pip install pyside2
安装)和 Manjaro Linux 18.0.4(通过 pacman
-packages pyside2
and pyside2-tools
).
注意:自版本 5.14.0(2019 年 12 月)起,上述解决方案中使用的 pyside2uic
模块已从 PySide2 代码库中删除。但是,随后在 PySide2 问题跟踪器上向“bring back loadUiType”提交了一个请求。从版本 5.14.2.2(2020 年 5 月)开始,loadUiType
可以从 QtUiTools
模块导入,并且就像在 PyQt5 中一样工作。这使得问题中提出的问题过时了。
PySide2 brought back loadUiType in May 2020。因此,如果您升级,可以获得 drop-in 替换。唯一的区别是导入:
from PySide2.QtUiTools import loadUiType
语法相同(您将使用 loadUiType(<file>)[0]
)
TL;DR:我想从其与 PySide2 和 [=55 一起使用的 uic
模块中直接替换 PyQt5 的 loadUiType()
函数=] 3.6+.
我想将 PyQt5 应用程序迁移到 PySide2。我使用的一个常见模式是,我在 Qt Designer 中创建用户界面设计并动态加载生成的 .ui
文件作为混合 class 在 Python 代码中扩展 Qt 小部件,比如主 window 本身:
from PyQt5 import QtWidgets, uic
class Window(QtWidgets.QMainWindow, uic.loadUiType('design.ui')[0]):
def __init__(self):
super().__init__()
self.setupUi(self)
print(self.label.text())
app = QtWidgets.QApplication([])
window = Window()
window.show()
app.exec_()
这意味着我可以放弃在命令行上将 .ui
设计编译为 .py
Python 模块。更重要的是,混合模式允许我在导入小部件的范围内通过 self.name
访问设计中定义的所有 Qt 小部件,其中 name
在 Qt Designer 中如此分配。
为了提供一个可重现的例子,这里有一个最小的 Qt 设计文件与上面的 Python 代码一起使用,其中它被引用为 design.ui
:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="label">
<property name="text">
<string>Hi, Qt.</string>
</property>
</widget>
</widget>
</widget>
</ui>
我想完成同样的事情,但使用 PySide2,并且代码更改尽可能少。问题是,PySide2 不提供 PyQt5 的 uic.loadUiType()
函数的等价物,重要的是,returns the design's form class 用作混合。
有一个相关的问题,"PyQt5 to PySide2, loading UI-Files in different classes", but its premise is that the loaded objects be usable from a separate class, which is not my concern per se. Plus, the (currently) only answer to it is not the solution I am looking for. Other questions and their answers (QtUiTools.QUiLoader().load('design.ui')
在 PySide2 中动态加载,但是该方法 returns widget 对象,不是要求的形式 class.
后一种方法,如果不混合导入的 class,将需要我为迁移更改许多代码行,因为它会导致 Python 实例变量的不同对象层次结构.在上面的示例中,self.label
然后必须在整个代码库中重命名为类似 self.ui.label
的内容。
我想要的是 PyQt5 的 loadUiType(design)
函数的直接替换,来自其 uic
模块,该模块与 PySide2 和 Python 3.6+ 一起使用,其中 design
指定.ui
文件的路径。
This answer,从 2013 年开始,完美地证明了这一点,但是对于 PySide(基于 Qt4)和(遗留)Python 2. 我如何使该代码适应 PySide2(基于 Qt5) 运行 在(现代)Python?
以下是 Python 3.6 或更高版本和 PySide2 5.13 或更旧版本(见末尾的注释)的改编版本 above-cited,较早的答案:
from PySide2 import QtWidgets
from pyside2uic import compileUi
from xml.etree import ElementTree
from io import StringIO
def loadUiType(design):
"""
PySide2 equivalent of PyQt5's `uic.loadUiType()` function.
Compiles the given `.ui` design file in-memory and executes the
resulting Python code. Returns form and base class.
"""
parsed_xml = ElementTree.parse(design)
widget_class = parsed_xml.find('widget').get('class')
form_class = parsed_xml.find('class').text
with open(design) as input:
output = StringIO()
compileUi(input, output, indent=0)
source_code = output.getvalue()
syntax_tree = compile(source_code, filename='<string>', mode='exec')
scope = {}
exec(syntax_tree, scope)
form_class = scope[f'Ui_{form_class}']
base_class = eval(f'QtWidgets.{widget_class}')
return (form_class, base_class)
如果与主 Python 模块一起另存为 uic.py
,则只需更改 import
语句即可将问题中的示例从 PyQt5 迁移到 PySide2:
from PySide2 import QtWidgets
import uic
在 Windows 10(通过 pip install pyside2
安装)和 Manjaro Linux 18.0.4(通过 pacman
-packages pyside2
and pyside2-tools
).
注意:自版本 5.14.0(2019 年 12 月)起,上述解决方案中使用的 pyside2uic
模块已从 PySide2 代码库中删除。但是,随后在 PySide2 问题跟踪器上向“bring back loadUiType”提交了一个请求。从版本 5.14.2.2(2020 年 5 月)开始,loadUiType
可以从 QtUiTools
模块导入,并且就像在 PyQt5 中一样工作。这使得问题中提出的问题过时了。
PySide2 brought back loadUiType in May 2020。因此,如果您升级,可以获得 drop-in 替换。唯一的区别是导入:
from PySide2.QtUiTools import loadUiType
语法相同(您将使用 loadUiType(<file>)[0]
)