QUiLoader not loading layouts from .ui file
I recently posted this on stackoverflow.com but I didn't get any response so I am trying here. Original stackoverflow post...
I have a plugin for an application which provides the ability to use PyQt4 to create widgets which they can use to make their own tools for the application. The QApplication is maintained by a C++ plugin and an 'anchor' widget is parented to the host application's window handle. Then the user can create their own widgets and use this 'anchor' to be the parent widget. This works very well for PyQt4. Recently, I have been attempting to provide support for PySide and this too is working well right up until I need to create widgets from .ui files. It seems that when I use QUiLoader to load my .ui file the my resulting widget doesn't look the same as in PyQt4. It looks as if it is missing or skipping layouts and other properties described in the .ui file, such as the title. Thing is when I log the return value of that load function I get what seems right...
@ class ExampleUiFile(QDialog):
def init(self, parent, uifilepath):
# load ui file loader = QUiLoader(self) file = QtCore.QFile(uifilepath) file.open(QtCore.QFile.ReadOnly) self.ui = loader.load(file, self) file.close() for k,v in vars(self.ui).items(): print("%s : %s" % (k,v)) # connect to the createCube function self.ui.uiCreateCube.clicked.connect(self.createCube) def createCube(self): print(self.ui.uiCubeName.text())@
@ horizontalLayout : <PySide.QtGui.QHBoxLayout object at 0x0000000023997308>
uiCubeName : <PySide.QtGui.QLineEdit object at 0x0000000023338508>
verticalLayout :<PySide.QtGui.QVBoxLayout object at 0x0000000023997548>
gridLayout : <PySide.QtGui.QGridLayout object at 0x0000000023997E08>
uiCubeLength : <PySide.QtGui.QDoubleSpinBox object at 0x0000000023338808>
uiCreateCube : <PySide.QtGui.QPushButton object at 0x0000000023338988>@
So in an attempt to fix this I went digging, here and elsewhere, and found examples of sub-classing QUiLoader. I was able to copy a simple class which inherits QUiLoader which does some extra work to return the initial base class. This guy seemed to have worked and my dialog looks correct, the correct title is shown, layout, and resizing works. Unfortunately, the garbage collector removes all the widgets that my loader class created and I get message about my object being deleted...
@ class UiLoader(QUiLoader):
def init(self, baseinstance):
self._baseinstance = baseinstance
def createWidget(self, classname, parent=None, name=""): widget = super(UiLoader, self).createWidget( classname, parent, name) if parent is None: return self._baseinstance else: setattr(self._baseinstance, name, widget) return widget@
Output using new sub-classed loader...
@ Internal C++ object (PySide.QtGui.QLineEdit) already deleted.@
I have done a lot of digging on this issue and some bug in PySide in the past seemed to be the culprit, but I am using PySide 1.1.2 which has it fixed. I even built PySide from source with 1.1.3dev and still the same. I should add that I wasn't able to reproduce this sub-classing issue outside of the host application. I was able to make a simple python/PySide example that worked as expected.
Where do I go from here, where should I look next? I get a good looking ui without the functionality or I get an ugly ui with the functionality. I would prefer not to sub-class the QUiLoader since I am not doing anything fancy with custom widgets or anything.