Question

I am learning PyQt4 (I am using version 4.4.4) and I'm pretty new to Python (Python 2.5). I have a GUI with a QListWidget and a QPushButton. I want a user to be able to click to select an entry in the list and then click the QPushButton and have the selected entry go away (be deleted from the QList). I've been banging my head against this problem for over a week and I would deeply appreciate some help.

Currently, my GUI comes up and I can select different list items (only one at a time right now), but when I click the QPushButton, nothing happens. The selection color goes from blue to grey, but the entry is not removed. No error is shown in Command Prompt (Windows 7).

I have defined a function, remove(),which I am using as the slot for the QPushButton. I believe the QPushButton.connect is defined correctly for a Qt Signal to Python Slot, based on what I've seen of answers to similar problems, but the items are not being deleted. However, the remove function is not even being triggered. I have a print statement within the function, but it is not being called when I click the QPushButton, which is how I know that the function is not being called.

Here is my most recent code: (I read a very rant-y post on meta-SO about big blocks of code, so I've cut this down to the bits I think are relevant: the list creation, the button creation and the remove function, which I'm trying to use as a slot. I've left in comments that indicate what the other sections are, so if you think I've left out something that could help, let me know and I'll add it back in)

class questionGUI(QtGui.QWidget):
#This class is the window of the gui.

    def __init__(self):
        super(questionGUI,self).__init__()
        #Layout
        grid = QtGui.QGridLayout()
        grid.setSpacing(10)

        #Labels Needed
        ...

        #Question List
        self.qList = QtGui.QListWidget()
        #print self.qList
        self.qList.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
        entries = ['[Pick Image] <Default>','[Slider Question] <Default>', '[Comment Box] <Default>']

        for i in entries:
            item = QtGui.QListWidgetItem(i)
            self.qList.addItem(item)

        #Type select
        ...

        #Text insert Needed
        ...

        #Buttons Needed
        deleteButton = QtGui.QPushButton('Delete Question')
        deleteButton.connect(deleteButton,QtCore.SIGNAL('itemClicked(clicked)'),lambda: self.remove)

        addQuestionButton = QtGui.QPushButton('Add Question')
        ...

        doneButton = QtGui.QPushButton('Done')
        ...

        #Parameters Needed
        ...

        #Layout Placement and Window dimensions
        ...

    def addQuestion(self):
        ...

    def remove(self):
        print 'remove triggered'
        print self.qList.currentItem()
        self.qList.removeItemWidget(self.qList.currentItem())

...

I tried to post an image, but I don't have enough reputation. If you think an image would be useful, let me know and I can send it to you.

Was it helpful?

Solution

You mixed the signals:

deleteButton.connect(deleteButton,QtCore.SIGNAL('itemClicked(clicked)'),lambda: self.remove)

deleteButton is a QPushButton, but itemClicked(clicked) looks like the signal from QListWidget with wrong signature. Since, QPushButton doesn't have this signal, no connection is made. Qt doesn't raise errors for failed connections, but .connect method has a bool return value indicating success/failure of the attempted connection.

Also, lambda: self.remove as a slot doesn't make sense. Slot should be a callable that is called upon signal emit. Sure, lambda creates a function, but all you do is reference the method self.remove. lambda will be called, self.remove not. Just self.remove as a slot is enough.

You should use clicked() signal (or clicked(bool), if you care about the checked value) from button:

deleteButton.connect(deleteButton, QtCore.SIGNAL('clicked()'), self.remove)

Edit

Another problem: Your remove method doesn't do what you want. removeItemWidget doesn't remove the item, it removes the widget inside the item (if you set one). It's counterpart to setItemWidget.

You should use takeItem to remove items.

def remove(self):
    self.qList.takeItem(self.qList.currentRow())
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top