5
votes

I have a QListWidget where I want to add a bunch of items with a custom widget:

        listWidget = QListWidget()
        item = QListWidgetItem()
        item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
        item.setCheckState(Qt.Unchecked)
        listWidget.addItem(item)
        widget = MyLabelAndPushButton()
        item.setSizeHint(widget.sizeHint())
        listWidget.setItemWidget(item, widget)

As the name suggests MyLabelAndPushButton is just a widget containing a QLabel and a QPushButton in a layout. The problem is that I can not use the checkbox that appears in the listwidget next to the widget. It looks completely normal, but nothing happens when I click on it. If I remove the line with setItemWidget it works correctly. What am I doing wrong?

edit:

Reported bug at bugreports.qt.io/browse/QTBUG-16386 but got the reply "API is not designed for what you intend to do" and "In case if you want to display custom widget, use QListView and subclass QItemDelegate." So apparently it's not a bug, just something the API can't handle.

2

2 Answers

2
votes

I'm not sure why exactly list item doesn't want to change its state when widget is set. I guess the workaround for this issue would be either adding a check box in your widget or connect to the listwidget's itemClicked signal and reset item's state there. Pls, see if an example below would work for you:

import sys
from PyQt4 import QtGui, QtCore

class MainForm(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        listWidget = QtGui.QListWidget()

        item = QtGui.QListWidgetItem()
        item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
        item.setCheckState(QtCore.Qt.Unchecked)
        listWidget.addItem(item)

        widget = QtGui.QCheckBox('test')
        item.setSizeHint(widget.sizeHint())
        listWidget.setItemWidget(item, widget)

        listWidget.itemClicked.connect(self.on_listWidget_itemClicked)

        self.setCentralWidget(listWidget)

    def on_listWidget_itemClicked(self, item):
        if item.listWidget().itemWidget(item) != None: 
            if item.checkState() == QtCore.Qt.Checked:
                item.setCheckState(QtCore.Qt.Unchecked)
            else:
                item.setCheckState(QtCore.Qt.Checked)

def main():
    app = QtGui.QApplication(sys.argv)
    form = MainForm()
    form.show()
    app.exec_()

if __name__ == '__main__':
    main()

hope this helps, regards

1
votes

The docs for QListWidget::setItemWidget say:

This function should only be used to display static content in the place of a list widget item. If you want to display custom dynamic content or implement a custom editor widget, use QListView and subclass QItemDelegate instead.

By "static content" I suppose it means non-interactive, indicating that this is a known limitation when using QListWidget.