TL;DR: I want a drop-in replacement for PyQt5's loadUiType()
function from its uic
module that works with PySide2 and Python 3.6+.
I want to migrate a PyQt5 application to PySide2. A common pattern I use is, I create the user-interface design in Qt Designer and dynamically load the resulting .ui
file as a mix-in class extending a Qt widget in the Python code, such as the main window itself:
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_()
This means I can forgo compiling the .ui
design to a .py
Python module on the command line. More importantly, the mix-in pattern lets me access all Qt widgets defined in the design via self.name
within the scope of the importing widgets, where name
is assigned as such within Qt Designer.
For the sake of providing a reproducible example, here is a minimal Qt design file to go along with the above Python code, in which it is referenced as 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>
I would like to accomplish the same, but with PySide2, and with the fewest code changes possible. The problem is, PySide2 does not provide an equivalent of PyQt5's uic.loadUiType()
function, which, importantly, returns the design's form class to be used as the mix-in.
There is a related question, "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 (1, 2) establish that design files can be dynamically loaded in PySide2, via QtUiTools.QUiLoader().load('design.ui')
, but that method returns the widget object, not the required form class.
The latter approach, without mixing in the imported class, would require me to change many lines of code for the migration, as it results in a different object hierarchy of the Python instance variables. In the above example, self.label
would then have to be renamed to something like self.ui.label
throughout the code base.
What I want is a drop-in replacement for PyQt5's loadUiType(design)
function from its uic
module that works with PySide2 and Python 3.6+, wherein design
designates the path to a .ui
file.
This answer, from 2013, perfectly demonstrates that, but for PySide (based on Qt4) and (legacy) Python 2. How do I adapt that code to PySide2 (based on Qt5) running on (modern) Python?