PyQt5 delete a QListWidgetItem when button in widget is pressed

Question:

I have a listWidget that contains multiple QListWidgetItem and for simplicity’s sake, let’s assume that each QListWidgetItem consists of a QWidget with a QPushButton called delete. This is assembled with this code:

class widgetItem(QtWidgets.QWidget):
    def __init__(self, parent):
        super(widgetItem, self).__init__()
        uic.loadUi('UIfiles/trainingWidget.ui', self) # Load the .ui file

        self.listWidgetItem = QtWidgets.QListWidgetItem()
        self.listWidgetItem.setSizeHint(self.sizeHint())
        self.delete.clicked.connect(self.deleteSelf)
        parent.listWidget.addItem(self.listWidgetItem)
        parent.listWidget.setItemWidget(self.listWidgetItem, self)

and this is called in the main app with this:

def additem(self):
    self.referenceDict[self.itemID] = widgetItem(self)  

Now, my goal is to delete this particular widget from both the referenceDict as well as the listWidget when the button is pressed. Each widgetItem also has their own itemID as a string, and can access the listWidget as well as the referenceDict. How do I write this deleteSelf? I’ve tried using self.deleteLater but it seems like it only deletes the QWidget but not the QListWidgetItem. Calling self.listWidgetItem.deleteLater raises an attribute error as it cannot be deleted this way. I also tried parent.referenceDict.pop(self.itemID) but for some reason it raises a key error despite both the keys matching when I printed the dict out.

Asked By: ChronoVortex

||

Answers:

You can remove listitems using the takeItem method and delete widgets using the deleteLater method.

I wasn’t to fond of your chosen process for creating the widgets and adding them to the list, so I went ahead and created a minimal example but using QPushButton instead of QWidgets for the itemWidgets.

Example:

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class Window(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)
        self.listWidget = QListWidget(self)
        self.layout.addWidget(self.listWidget)
        self.addListItems()

    def addListItems(self):           # creates the item widgets
        for _ in range(5):
            item = QListWidgetItem(type=0)
            widget = ListItem("button", self, item)
            self.listWidget.addItem(item)
            self.listWidget.setItemWidget(item, widget)

    def removeWidgetItem(self, item):  # removes the item widgets
        index = self.listWidget.indexFromItem(item).row()
        item = self.listWidget.takeItem(index)

class ListItem(QPushButton):

    def __init__(self, text, parent, item):
        super().__init__(text, parent)
        self.item = item                     # the ListWidgetItem
        self._parent = parent                # the Window
        self.clicked.connect(self.deleteSelf)

    def deleteSelf(self):                    # slot for button click
        self._parent.removeWidgetItem(self.item)
        self.deleteLater()

app = QApplication([])
window = Window()
window.show()
app.exec()
Answered By: Alexander
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.