Can't change state of checkable QListViewItem with custom widget
Asked Answered
N

2

6

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.

Nickname answered 22/12, 2010 at 14:47 Comment(0)
C
2

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

Coercion answered 24/12, 2010 at 18:53 Comment(1)
It would work as a last resort, but I'd rather try to avoid using workarounds like this.Nickname
F
1

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.

Foetus answered 29/12, 2010 at 3:55 Comment(1)
Good theory, but the checkbox (created by the QListWidgetItem itself) does not work with non-interactive content either, such as a QLabel.Nickname

© 2022 - 2024 — McMap. All rights reserved.