I'm trying to get this custom frame be usable as a widget in qt-designer. I'm following this example in pyqt5 documentation. I've implemented subclasses of QPyDesignerContainerExtension
, CollapsibleBoxExtensionFactory
and QPyDesignerCustomWidgetPlugin
. The only difference is that the example involves pages, and mine is just a custom frame. It is the only example demonstrating a container plugin, and therefore, using the class QPyDesignerContainerExtension
.
All function of the widget work when used in python, it appears in qt-designer, but I'm unable to drop a widget in it. Except if I force getCurrentIndex to be 0 instead of -1 when the frame is empty. But this obviously create a segmentation fault error in qt designer as it tries to access a non existing widget.
After a bit of reverse ingeneering on how qt designer interact with multipagewidgetplugin, I have the impression that the QPyDesignerContainerExtension
is more for multipage containers that for basic frames.
Is QPyDesignerContainerExtension
supposed to work with basic containers, as a frame ? Or should I be looking for a bug in my code...
Thanks for any help
edit: To refocus the question on the primary problem, here is a simple version of the widget I want to use in qt-designer
The widget:
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QWidget, QScrollArea, QSizePolicy, QVBoxLayout, QLabel
class CustomFrame(QWidget):
def __init__(self, parent=None, title='title'):
super().__init__(parent)
layout = QVBoxLayout(self)
self.setLayout(layout)
self.title = QLabel(text=title)
layout.addWidget(self.title)
self.content_area = QScrollArea()
# self.content_area.setMinimumHeight(0)
# self.content_area.setMaximumHeight(0)
self.content_area.setSizePolicy(
QSizePolicy.Expanding, QSizePolicy.Fixed
)
layout.addWidget(self.content_area)
self.content_layout = QVBoxLayout(self.content_area)
self.content_area.setLayout(self.content_layout)
def _update_animation(self):
# need to be called each time a widget is added
pass
def getTitle(self):
return self.toggle_button.text()
@pyqtSlot(str)
def setTitle(self, value):
self.toggle_button.setText(value)
def resetTitle(self):
self.toggle_button.setText("Title")
titleString = pyqtProperty(str, getTitle, setTitle, resetTitle)
A plugin:
from PyQt5.QtDesigner import QPyDesignerCustomWidgetPlugin
class MultiPageWidgetPlugin(QPyDesignerCustomWidgetPlugin):
def __init__(self, parent=None):
super(MultiPageWidgetPlugin, self).__init__(parent)
self.initialized = False
def initialize(self, formEditor):
if self.initialized:
return
self.initialized = True
def isInitialized(self):
return self.initialized
def createWidget(self, parent):
widget = CustomFrame(parent)
return widget
def name(self):
return "CustomFrame"
def group(self):
return "PyQt Examples"
def icon(self):
return QIcon()
def toolTip(self):
return ""
def whatsThis(self):
return ""
def isContainer(self):
return True
def domXml(self):
return ('<widget class="CustomFrame" name="customframe">'
' <widget class="QWidget" name="page" />'
'</widget>')
def includeFile(self):
return "customframe"
The goal is, in qt-designer, that a widget dropped to the CustomFrame is added to content_area
. By setting isContainer() to true, the widget accept dropped widgets, but they are added the widget itself, not to content_area
. So unless there is a way to change this behaviour, It seems to be requiered to use a QPyDesignerContainerExtension with a single page...