Pyside/PyQt - Attach QWidget to QGraphicsItem

Has anyone been able to attach an standard QWidget to a QGraphicsItem, say a QSpinBox to modify a float value that the QGraphicsItem is representing?
I know it is possible to add a QWidget to a QGraphicsScene but I want to attach it to an Item in my Scene, rather than the scene itself.

Thanks muchly in advance.

I’m not sure QGraphicsItem supports that directly unless you paint it in yourself. I think what you’re looking for if you want to display widgets is an inheritor called QGraphicsWidget. Then you can just add it as a child of your custom QGraphicsItem. http://doc.qt.io/qt-5/qgraphicswidget.html

Thanks for the reply Claudio,

There doesn’t seem to be any method on the QGraphicsWidget to add a standard widget as a child.
My current plan/work around is to add a standard widget to the scene, overlaying it on top of the QGraphicsItem/Widget and then use a custom moving signal to keep the standard widget aligned to the Graphics widget if/when it is moved.

Here’s a proof of concept, but probably not the most efficient. You need to use a special layout reserved for GraphicsWidget items. I inherited in this example, but the documentation proposes composition if you’re simply adding widgets to a scene. More importantly is that widgets need to be added to the scene despite all other requirements. Note that I parented the QGraphicsWidget to a QGraphicsRectItem and it works as intended.

import sys
from Qt import QtWidgets, QtCore


class TestGraphicsWidget(QtWidgets.QGraphicsWidget):
    """

    """
    comboBoxIndexChanged = QtCore.Signal(str)
    lineEditTextChanged = QtCore.Signal(str)

    def __init__(self, scene=None):
        super(TestGraphicsWidget, self).__init__(parent=None)

        combo = QtWidgets.QComboBox()
        combo.addItems([str(i) for i in range(5)])
        combo.currentIndexChanged[unicode].connect(self.comboBoxIndexChanged)

        line = QtWidgets.QLineEdit()
        line.textChanged.connect(self.lineEditTextChanged)

        self.lineEdit = scene.addWidget(line)
        self.comboBox = scene.addWidget(combo)


        layout = QtWidgets.QGraphicsLinearLayout()
        layout.addItem(self.lineEdit)
        layout.addItem(self.comboBox)

        self.setLayout(layout)


class Window(QtWidgets.QDialog):
    """

    """
    def __init__(self, parent=None):
        super(Window, self).__init__(parent=parent)
        self.scene = QtWidgets.QGraphicsScene()
        self.view = QtWidgets.QGraphicsView(self.scene)

        self.pushButtonAdd = QtWidgets.QPushButton('Add')

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.view)
        layout.addWidget(self.pushButtonAdd)

        self.setLayout(layout)

        self.pushButtonAdd.pressed.connect(self.addTestItem)

    @QtCore.Slot(object)
    def printOutput(self, text):
        print(text)

    @QtCore.Slot()
    def addTestItem(self):
        """

        :return:
        """
        item = QtWidgets.QGraphicsRectItem()
        item.setRect(QtCore.QRectF(0, 0, 200, 40))
        w = TestGraphicsWidget(self.scene)
        w.setParentItem(item)
        w.comboBoxIndexChanged.connect(self.printOutput)
        w.lineEditTextChanged.connect(self.printOutput)
        self.scene.addItem(item)


if __name__ in ('__main__', '__builtin__'):

    app = QtWidgets.QApplication.instance() or QtWidgets.QApplication(sys.argv)
    app.setStyle('plastique')

    dialog = Window(None)
    dialog.show()
    sys.exit(app.exec_())

Thank you sir, you are a hero!
I will review this and post back with anything else I figure out.