I get this error when I try to refer to my custom class from .ui
file. What's wrong with what I do?
"QFormBuilder was unable to create a custom widget of the class 'TimelinePane'; defaulting to base class 'QWidget'."
QWidget
pops up with the layout I'm specifying in .ui
file. Problem is just the custom class.
To add the custom class' description, I modified .ui
file manually (added the entire <customwidgets>
section), which is why I have to open a new question since I haven't found the same Q yet. I suspect the path of the class in .ui
file but none of the options I tried (see the part I commented out) worked. I also guess that using python
should not be the matter here but am not entirely sure. Haven't tried C++
yet.
from PySide import QtGui
from PySide import QtCore
from PySide import QtUiTools
class MyWidget(QtGui.QMainWindow):
def __init__(self, *args):
apply(QtGui.QMainWindow.__init__, (self,) + args)
loader = QtUiTools.QUiLoader()
file = QtCore.QFile('./src/prove_qt_ui_file/prove_main_widget.ui')
file.open(QtCore.QFile.ReadOnly)
self.myWidget = loader.load(file, self)
file.close()
self.setCentralWidget(self.myWidget)
if __name__ == '__main__':
import sys
import os
print("Running in " + os.getcwd() + " .\n")
app = QtGui.QApplication(sys.argv)
win = MyWidget()
win.show()
app.exec_()
prove_main_widget.ui
<?xml version="1.0" encoding="UTF-8" ?>
<ui version="4.0">
<class>MyWidget</class>
<widget class="QWidget" name="MyWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>687</width>
<height>698</height>
</rect>
</property>
<property name="windowTitle">
<string>Runtime Monitor</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="handleWidth">
<number>9</number>
</property>
<widget class="QTreeWidget" name="warn_tree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
<widget class="QTreeWidget" name="tree_all_devices">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
<widget class="TimelinePane" name="timeline_pane" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>80</height>
</size>
</property>
<property name="whatsThis">
<string extracomment="Timeline"/>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>TimelinePane</class>
<extends>QWidget</extends>
<!-- <header>timeline_pane</header> --> <!-- NG -->
<!-- <header>prove_qt_ui_file.timeline_pane</header> --> <!-- NG -->
<header>src.prove_qt_ui_file.timeline_pane</header> <!-- NG -->
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
timeline_pane.py
from PySide.QtGui import QWidget, QGraphicsScene, QGraphicsView, QColor, QHBoxLayout, QPushButton
class TimelinePane(QWidget):
def __init__(self, parent):
super(TimelinePane, self).__init__()
print '\tTimelinePane init 1' # This doesn't print.
(Environment) Ubuntu 12.04, python 2.7.3
In theory, to have your custom widget work you should only have to call:
before calling loader.load(). You need to add the relevant import statements, in your case:
However, I just tested this with PySide 1.1.2 on Ubuntu 12.04 x86_64, and it caused a segfault. YMMV, so please test.
I ended up implementing this workaround: http://www.mail-archive.com/pyside@qt-project.org/msg00306.html
In short, override the QUiLoader's creteWidget() method, and if the class_name of the widget is not in self.availableWidgets(), instantiate it yourself according to the customWidgets instance variable that you've added.
BTW, you can also make use of the right-click "Promote To" functionality in the Qt Designer instead of editing the ui file directly.