0

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.

SatelliteEyes
  • 75
  • 1
  • 8
  • PyQt 4.4.4 is really old. Is there any reason to use such an ancient version? – Avaris Apr 03 '13 at 19:59
  • Firstly: I work for a defense contractor. Our IT dept. maintains a tightly controlled list of 'approved' software which is always a number of versions behind. I'm still working with Python 2.5. Yes, it's dumb. Secondly: I'm also not an admin on my own computer, so I can't just download this open source software and use them to get around IT. Third, and most importantly: This is part of a project to update an old internal software program, in Py2.5 and PyQt4.4.4, which is 1000s of lines long and in constant use. Taking it offline to rewrite the whole thing in Py3.0 and PyQt5 is not an option. – SatelliteEyes Apr 04 '13 at 00:03
  • I see. Version is not related to your problem. It just caught my eye as "odd". But, if it is tied to some legacy code, it makes sense. – Avaris Apr 04 '13 at 00:15

1 Answers1

1

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())
Avaris
  • 35,883
  • 7
  • 81
  • 72
  • This works! Thank you so much for your help! I thought that I essentially needed two signals: the click on the list to select the item and the click on the button to remove it. itemClicked is a QListWidget function and it was my attempt to use both those signals. I understand now that that is unnecessary, since clicking on a list entry will automatically update the current row or item, so explicitly saying an item has been clicked is not necessary. – SatelliteEyes Apr 04 '13 at 14:57
  • @Avaris please look at question http://stackoverflow.com/questions/16221810/how-to-handle-mouse-events-in-qt . Thanks. – Alex Apr 26 '13 at 16:36