[PySide] QtUiTools.QUiLoader crash with custom widget

Tyler W. Wilson tyler at tylerlabs.com
Tue May 1 17:42:31 CEST 2012

On 5/1/2012 5:37 AM, Ludo Visser wrote:
> On Apr 30, 2012, at 5:16 pm, Tyler W. Wilson wrote:
>> Ditto on this issue for me. I just ran into this as well trying to add a
>> custom widget to a designer-based application. I had to move to PyQt4
>> temporarily to make it work.
>> Thanks,
>> Tyler
>> On 4/30/2012 9:58 AM, Stefan wrote:
>>> Hi,
>>> I'm trying to create a QMainWindow in the Designer and load the ui file
>>> dynamically with QUiLoader in pyside 1.1.0. When I don't register any
>>> custom types it works, but obviously fails to create my derived class.
>>> When I register them it crashes. Here's a small example that crash for
>>> me on windows running python 2.7 and pyside 1.1.0:
>>> from PySide import QtCore, QtGui, QtUiTools
>>> import sys
>>> class MyWidget(QtGui.QWidget):
>>>       def __init__(self, parent=None):
>>>           super(MyWidget, self).__init__(parent)
>>> if __name__ == '__main__':
>>>       application = QtGui.QApplication(sys.argv)
>>>       loader = QtUiTools.QUiLoader()
>>>       loader.registerCustomWidget(MyWidget)
>>>       print loader.availableWidgets()
>>>       print loader.createWidget('QLabel')
>>>       print loader.createWidget('MyWidget')
>>> Running this prints the following:
>>> [...]
>>> So it the class is in there, it manages to create a QLabel, but then it
>>> crashes.
>>> Any ideas why? I don't have any pdb for python, so it's hard to get a
>>> callstack.
>>> /Stefan
> I'm not sure what is causing the crash, but one way to obtain the functionality you require is to subclass the QUiLoader class to handle your custom widgets (see http://www.mail-archive.com/pyside@lists.openbossa.org/msg00878.html). For example something like this (here, a top-level widget is used to wrap around the ui-loaded widget, and this top-level widget has an attribute specifying which custom widgets it wants to load; of course, different approaches are possible):
>   def createWidget(self, className, parent = None, name = ""):
>      if className in QtUiTools.QUiLoader.availableWidgets(self):
>          widget = QtUiTools.QUiLoader.createWidget(self, className, parent, name)
>      else:
>          if hasattr(self.baseinstance, "customWidgets"):
>              if className in self.baseinstance.customWidgets.keys():
>                  widget = self.baseinstance.customWidgets[className](parent)
>              else:
>                  raise KeyError("Unknown widget '%s'" % className)
>          else:
>              raise AttributeError("Trying to load custom widget '%s', but base instance '%s' does not specify custom widgets." % (className, repr(self.baseinstance)))
>      if self.baseinstance is not None:
>          setattr(self.baseinstance, name, widget)
>      return widget
No doubt the issue might be worked around like shown above, but it seems 
like the base UILoader ought to handle this transparently, especially 
considering there is a section in .ui file that specifies the custom 
widgets. Plus, it does work in PyQt4. For example, my .ui includes this:


So I would expect the base UILoader to look at this section and perform 
the proper imports to make these widgets available.

But thank you for the tip on the work-around.

- Tyler

More information about the PySide mailing list