This is a partial answer which may not be exactly what you are looking for but perhaps a pointer to get you started. I think, in theory, the solution (or at least best avenue of research) is the QGraphicsProxyWidget class.
I made a few tests and achieved some, but not perfect results.
The following code snippet adds a QWidget
with child sub-widgets to a QgsPrintLayout
object.
class TestProxyWidget(QGraphicsProxyWidget):
def __init__(self):
QGraphicsProxyWidget.__init__(self)
self.w = CustomWidget()
self.setWidget(self.w)
class CustomWidget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.layout = QHBoxLayout()
self.lbl = QLabel('A Label:', self)
self.le = QLineEdit(self)
for w in self.children():
self.layout.addWidget(w)
self.setLayout(self.layout)
project = QgsProject.instance()
mgr = project.layoutManager()
layout = mgr.layoutByName('Test Layout')
proxy = TestProxyWidget()
layout.addItem(proxy)
The results are shown below, but as you can see- the size of the added widget is very large and I couldn't easily work out how to resize/scale the widget. Familiar methods like SetGeometry()
, resize()
, setMinimumSize()
, setMaximumSize()
etc don't work very well here. You can resize the parent widget, but the child widgets like labels, line edits, push buttons etc. don't scale properly. I'm sure there is a different approach to controlling the size but I'm not expert in this area as I haven't worked that much with Qt graphics classes and, unfortunately I don't much time at the moment to put into research.

If you do something like this example in the docs:
class CustomWidget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.layout = QHBoxLayout()
self.lbl = QLabel('A Label:', self)
self.cb = QComboBox(self)
self.cb.addItems(['Large', 'Medium', 'Small'])
self.pb = QPushButton('Click me', self)
for w in self.children():
self.layout.addWidget(w)
self.setLayout(self.layout)
CW = CustomWidget()
scene = QGraphicsScene()
proxy = scene.addWidget(CW)
view = QGraphicsView(scene)
view.show()
The result looks like:

Perhaps this is more of a PyQt question (which might be better asked on Stack Overflow) or if you are lucky, a QGIS developer who knows a lot more about this than I do will give you a better answer here.