1

I'm trying to make some new QPushButton from list of rows and then connect them to an Event Handler Function using connect but no matter what i do, i can't connect them separately to the function. the code is like this

def addItemButtons(self,chosen):

    # ----------- DELETE OLD BUTTONS ------------
    for i in reversed(range(self.layoutbottom.count())):
        self.layoutbottom.itemAt(i).widget().setParent(None)

    # ----------- MAKE A NEW BUTTON FOR EACH CHOSEN ENTRY -----------
    for d in chosen:
        itembtn = QPushButton("ID : "+str(d['id']))
        itembtn.clicked.connect(lambda : self.handlerFunction(str(d['id'])))
        self.layoutbottom.addWidget(itembtn)

def handlerFunction(self,txt):
    print(txt)

when I click on new buttons the handlerFucntion just prints the last button id!

I searched and used different methods for connecting buttons to handlerFunction but all were the same.

what is it that I am doing wrong? :/

Babakslt
  • 199
  • 1
  • 10
  • 1
    it can be common problem with `lambda` in `for` loop. `lambda` is "lazy" - it doesn't get value from `d` when you define `lambda` function but when you execute this function - when you click button. But when you click button then `d` is set on last element from list - so every button use the same `d` - last `d`. Common solution: `lambda x=d['id']: self.handlerFunction(str(x))`. It copy value from `d['id']` to `x` and every `lambda` use own `x`. – furas Nov 02 '16 at 20:32

2 Answers2

2

The problem was that the value of d['id'] wasn't being evaluated until after the loop had completed, so while all the buttons were being connected, only the last id was being sent. You need to ensure that the id value is evaluated during the loop.

You can use functools.partial to do this

from functools import partial

for d in chosen:
    itembtn = QPushButton("ID : "+str(d['id']))
    itembtn.clicked.connect(partial(self.handlerFunction, str(d['id'])))
    self.layoutbottom.addWidget(itembtn)
Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
1

well! i solved it but i don't know exactly how! this is what i did to solve the problem:

     for d in chosen:
        itembtn = QPushButton("ID : "+str(d['id']))
        self.connect(itembtn,SIGNAL('clicked()'),self.handleFunction)
        self.layoutbottom.addWidget(itembtn)

and then i changed the handlerFunction to this:

    def handleDriverSelection(self):
        print (self.sender().text()

i did the same thing before but with the diffrence of connecting buttons after making all of them and it was now working! maybe i did something wrong there. anyway. this is working for me. :)

Babakslt
  • 199
  • 1
  • 10
  • You didn't need to change the connect to use the old-style syntax. You could switch that part back, since the old-style syntax is generally discouraged. – Brendan Abel Nov 02 '16 at 23:26