0
votes

How do i add a custom qwidget to a QListWidget in order to gain list widget features like selection, scrolling, improved memory management, etc.

My goal is to create a layermanager similar to what many of you have seen in programs like Photoshop or Affinity Photo. I will eventually be extending my LayerWidget to have more controls than just a simple Label and Checkbox.

A previous question here (https://stackoverflow.com/a/30802784/3156300) on SO a user mentions using a QListWidget and QListWidgetItem to create what I'm attempting to do. However after further research I've come up short on figuring out how to take my custom widget and append it to the listWidget like he mentions.

enter image description here

Photoshop/Affinity Photo

enter image description here

import sys
from PySide import QtGui, QtCore


class LayerObject(object):

    def __init__(self, **kwargs):
        self.name = kwargs.get('name', '')
        self.enabled = kwargs.get('enabled', False)


class LayerWidget(QtGui.QWidget):

    def __init__(self, layer):
        super(LayerWidget, self).__init__()
        self.resize(400, 50)

        # controls
        self.ui_enabled = QtGui.QCheckBox()
        self.ui_layername = QtGui.QLabel()
        self.ui_items = QtGui.QComboBox()
        self.ui_items.addItems(['Color','Saturation','Blend'])

        main_layout = QtGui.QHBoxLayout()
        main_layout.addWidget(self.ui_layername)
        main_layout.addWidget(self.ui_items)
        main_layout.addStretch()
        main_layout.addWidget(self.ui_enabled)
        self.setLayout(main_layout)

        # construct
        self._layer = None
        self.layer = layer


    # properties
    @property
    def layer(self):
        return self._layer

    @layer.setter
    def layer(self, value):
        self._layer== value
        self.ui_layername.setText(value.name)
        self.ui_enabled.setChecked(value.enabled)


class LayerManager(QtGui.QWidget):
    def __init__(self):
        super(LayerManager, self).__init__()
        self.resize(400, 300)

        # controls
        self.ui_scroll = QtGui.QWidget()
        self.ui_scroll_layout = QtGui.QVBoxLayout()
        self.ui_scroll.setLayout(self.ui_scroll_layout)

        self.ui_scroll_area = QtGui.QScrollArea()
        self.ui_scroll_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.ui_scroll_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.ui_scroll_area.setWidgetResizable(True)
        self.ui_scroll_area.setWidget(self.ui_scroll)

        main_layout = QtGui.QHBoxLayout()
        main_layout.addWidget(self.ui_scroll_area)
        self.setLayout(main_layout)


        self.add_layers()

    def add_layers(self):
        layers = [
            LayerObject(name='Layer001', enabled=False),
            LayerObject(name='Layer002', enabled=False),
            LayerObject(name='Layer003', enabled=True),
            LayerObject(name='Layer004', enabled=False),
            LayerObject(name='Layer005', enabled=True),
            LayerObject(name='Layer006', enabled=False),
            LayerObject(name='Layer007', enabled=False),
            LayerObject(name='Layer008', enabled=True),
            LayerObject(name='Layer009', enabled=False),
            LayerObject(name='Layer010', enabled=True)
        ]

        for x in layers:
            widget = LayerWidget(layer=x)
            self.ui_scroll_layout.addWidget(widget)


def main():
    app = QtGui.QApplication(sys.argv)
    ex = LayerManager()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
1

1 Answers

1
votes

to add a widget you must use the method setItemWidget(), to this method you must pass the method to the QListWidgetItem, for this you can add it through the insertItem() method. One of the problems observed is that the size of the item does not correspond to the size of the widget, for this you must use sizeHint():

class LayerManager(QtGui.QWidget):
    def __init__(self):
        super(LayerManager, self).__init__()
        self.resize(400, 300)
        self.list_widget = QtGui.QListWidget()
        main_layout = QtGui.QHBoxLayout(self)
        main_layout.addWidget(self.list_widget)
        self.add_layers()

    def add_layers(self):
        layers = [
            LayerObject(name='Layer001', enabled=False),
            LayerObject(name='Layer002', enabled=False),
            LayerObject(name='Layer003', enabled=True),
            LayerObject(name='Layer004', enabled=False),
            LayerObject(name='Layer005', enabled=True),
            LayerObject(name='Layer006', enabled=False),
            LayerObject(name='Layer007', enabled=False),
            LayerObject(name='Layer008', enabled=True),
            LayerObject(name='Layer009', enabled=False),
            LayerObject(name='Layer010', enabled=True)
        ]

        for x in layers:
            widget = LayerWidget(layer=x)
            item =  QtGui.QListWidgetItem()
            self.list_widget.insertItem(self.list_widget.count(), item)
            self.list_widget.setItemWidget(item, widget)
            item.setSizeHint(widget.sizeHint())

enter image description here