Search code examples
pythonpyqtpyqt4qgraphicssceneqgraphicsitem

PyQt QGraphicsLayout Stacking


I am trying to create a qgraphicslayout in Pyqt4. I have a series of QGraphicsLayoutItems but they seem to be stacking in the layout instead of spacing. On the left, the items are all ontop of each other.

Example of the Stacking

Since the QGraphicsLayoutItem is abstract, I overrode it in the following class:

class AttributeGFX(QtGui.QGraphicsLayoutItem):
"""Wrapper."""

def __init__(self,
             n_x,
             n_y,
             n_scene,
             n_settings,
             n_name,
             n_type,
             n_io):
    """Init."""
    super(AttributeGFX, self).__init__()
    self.io = n_io
    self.name = n_name

    # Use same object for inputs and outputs
    self.is_input = True
    if "output" in n_io:
        self.is_input = False


    if self.is_input:
        self.disp_settings = n_settings.display_settings['INPUTS']
    else:
        self.disp_settings = n_settings.display_settings['OUTPUTS']

    if n_type not in self.disp_settings.keys():
        self.disp_settings = self.disp_settings['default']
    else:
        self.disp_settings = self.disp_settings[n_type]


    self.gitem = _AttributeGFX(n_x,
                               n_y,
                               n_scene,
                               n_settings,
                               n_name,
                               n_type,
                               n_io)
    self.setGraphicsItem(self.gitem)

def sizeHint(self, z, sizeh):
    """Get the size."""
    boundingrec = self.gitem.boundingRect()
    r = QtCore.QSizeF()
    r.setHeight(boundingrec.height())
    r.setWidth(boundingrec.width())
    return r

I thought that maybe it was the size hint, so I tried large floats in the QSizeF object instead of the bounding rec of the graphicsitem within the layout item.

Any idea whats going on? Below is where I am creating the layout and adding the items.

class _GraphicsLayout (QtGui.QGraphicsWidget):
    """Provide structure for organizing elements."""

    def __init__(self, spacing, parent):
        """Init."""
        super(_GraphicsLayout, self).__init__(parent)
        self.layout = QtGui.QGraphicsLinearLayout()
        self.layout.setSpacing(spacing)
        self.layout.setOrientation(QtCore.Qt.Vertical)
        self.layout.addStretch()
        self.setLayout(self.layout)
        self.name = self.parentItem().name
        self.items = {}
        self.spacing = spacing

    def add_item(self, item):
        """Add a new item to the layout and transform it into position."""
        '''
        trans = self.spacing * len(self.items) - 1 + item.height
        item.setParentItem(self)
        item.translate(0, trans)
        '''
        self.items[item.name] = item
        self.layout.addItem(self.items[item.name])
        self.layout.setSpacing(self.spacing)

EDIT: I printed parentLayoutItem on the QGraphicsLayoutItems and they are in the layout.


Solution

  • I found that not only do you need to override the sizeHint function in the qGraphicsLayoutItem class, but also the setGeometry function. I am not sure if I need to override the updateGeometry function but we will see: Examples and Docs

    Final Class:

    class AttributeGFX(QtGui.QGraphicsLayoutItem):
        """Wrapper."""
    
        def __init__(self,
                     n_x,
                     n_y,
                     n_scene,
                     n_settings,
                     n_name,
                     n_type,
                     n_io):
            """Init."""
            super(AttributeGFX, self).__init__()
            self.io = n_io
            self.name = n_name
    
            # Use same object for inputs and outputs
            self.is_input = True
            if "output" in n_io:
                self.is_input = False
    
    
            if self.is_input:
                self.disp_settings = n_settings.display_settings['INPUTS']
            else:
                self.disp_settings = n_settings.display_settings['OUTPUTS']
    
            if n_type not in self.disp_settings.keys():
                self.disp_settings = self.disp_settings['default']
            else:
                self.disp_settings = self.disp_settings[n_type]
    
    
            self.gitem = _AttributeGFX(n_x,
                                       n_y,
                                       n_scene,
                                       n_settings,
                                       n_name,
                                       n_type,
                                       n_io)
            self.setGraphicsItem(self.gitem)
            self.setMinimumHeight(3)
    
        def sizeHint(self, z, sizeh):
            """Get the size."""
            boundingrec = self.gitem.boundingRect()
            r = QtCore.QSizeF()
            r.setHeight(boundingrec.height())
            r.setWidth(boundingrec.width())
            return r
    
        def setGeometry(self, x):
            """Set geo size."""
            self.gitem.setPos(x.topLeft())