ano*_*non 5 python qt-designer python-3.x pyqt5 pyside2
TL;DR:我想要一个直接替换 PyQt5 的loadUiType()功能的uic模块,它可以与 PySide2 和 Python 3.6+ 一起使用。
我想将 PyQt5 应用程序迁移到 PySide2。我使用的一个常见模式是,我在 Qt Designer 中创建用户界面设计,并动态加载生成的.ui文件作为扩展 Python 代码中 Qt 小部件的混合类,例如主窗口本身:
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_()
Run Code Online (Sandbox Code Playgroud)
这意味着我可以放弃在命令行上将.ui设计编译为.pyPython 模块。更重要的是,混合模式让我可以通过self.name导入窗口小部件的范围内访问设计中定义的所有 Qt 窗口小部件,name在 Qt 设计器中指定的位置。
为了提供可重现的示例,这里有一个与上述 Python 代码一起使用的最小 Qt 设计文件,其中引用为design.ui:
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_()
Run Code Online (Sandbox Code Playgroud)
我想完成同样的事情,但使用 PySide2,并且代码更改尽可能少。问题是,PySide2 没有提供 PyQt5 的等价uic.loadUiType()函数,重要的是,它返回设计的表单类以用作混合。
有一个相关的问题,“PyQt5 到 PySide2,在不同的类中加载 UI 文件”,但其前提是加载的对象可以从单独的类中使用,这本身不是我关心的问题。另外,(目前)唯一的答案不是我正在寻找的解决方案。其他问题及其答案 ( 1 , 2 ) 表明设计文件可以通过 动态加载到 PySide2 中QtUiTools.QUiLoader().load('design.ui'),但该方法返回小部件对象,而不是所需的表单类。
后一种方法不混入导入的类,需要我为迁移更改多行代码,因为它会导致 Python 实例变量的对象层次结构不同。在上面的示例中,self.label则必须self.ui.label在整个代码库中重命名为类似的名称。
我想要的是 PyQt5 的loadUiType(design)函数从其uic与 PySide2 和 Python 3.6+ 一起工作的模块中直接替换,其中design指定.ui文件的路径。
这个来自 2013 年的答案完美地证明了这一点,但是对于 PySide(基于 Qt4)和(旧版)Python 2。我如何将该代码改编为在(现代)Python 上运行的 PySide2(基于 Qt5)?
以下是上述引用的早期答案中提出的解决方案针对 Python 3.6 或更高版本和 PySide2 5.13 或更低版本(请参阅末尾的注释)的改编:
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)
Run Code Online (Sandbox Code Playgroud)
如果uic.py与主 Python 模块一起保存,则只需import更改语句即可将问题中的示例从 PyQt5 迁移到 PySide2:
from PySide2 import QtWidgets
import uic
Run Code Online (Sandbox Code Playgroud)
在 Windows 10(通过pip install pyside2)和 Manjaro Linux 18.0.4(通过pacman-packagespyside2 和 pyside2-tools)上使用 Python 3.7.3 和 PySide2 5.12.3 进行测试。
注意:pyside2uic自版本 5.14.0(2019 年 12 月)起,上述解决方案中使用的模块已从 PySide2 代码库中删除。然而,随后在 PySide2 问题跟踪器上提出了“恢复 loadUiType ”的请求。从版本 5.14.2.2(2020 年 5 月)开始,loadUiType可以从模块导入QtUiTools并像在 PyQt5 中一样工作。这使得问题中提出的问题变得过时。
| 归档时间: |
|
| 查看次数: |
1991 次 |
| 最近记录: |