TKinter using an indexing for loop to pass arguments for a button command

Question:

I have the following piece of code in which I am creating a series of buttons to run an increase or decrease method on a created number class.

    for idx in range(len(self._priceNums)):
        Button(window, text='^', command=lambda: self.incNum(idx)).grid(row=0, column=numInColumn)
        Label(window, textvariable=self._priceNums[idx]).grid(row=1, column=numInColumn)
        Button(window, text='v', command=lambda: self.decNum(idx)).grid(row=2, column=numInColumn)
        numInColumn += 1

The function works as intended on the selected objects in the list, but my problem is getting the buttons to operate on the correct object. The

lamba: self.incNum(idx)

seems to read idx only when the button is pressed. Therefore every button only runs the method on the last object in the list. Is there a way to create a series of buttons in this way, each one corresponding to its respective number object in this list. Here is the method for reference

def incNum(self, idx):
    self._priceNums[idx].set(self.game._adjustedPrice[idx].incNum())

Note that may or may not be helpful:

_priceNums is a list of StringVars corresponding to the values of the number objects in _adjustedPrice

Thank you!

Asked By: Andrew Thomas

||

Answers:

You need to pass the idx variable to the lambda function.

for idx in range(len(self._priceNums)):
    Button(window, text='^', command=lambda idx=idx: self.incNum(idx)).grid(row=0, column=numInColumn)
    Label(window, textvariable=self._priceNums[lambda idx=idx: idx]).grid(row=1, column=numInColumn)
    Button(window, text='v', command=lambda idx=idx: self.decNum(idx)).grid(row=2, column=numInColumn)
    numInColumn += 1
Answered By: SolarFactories