[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:

<customwidgets>
<customwidget>
<class>QGradient</class>
<extends>QWidget</extends>
<header>QGradient</header>
<container>1</container>
</customwidget>
</customwidgets>

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