zbalda
zbalda

Reputation: 101

Making Buttons that Locate Themselves in a List

I am trying to create buttons that delete themselves. In the code below, I create some amount of buttons in a for loop, append them to a list, and grid them. I am able to delete and remove any button in a certain index position of the buttons list, but need to figure out how to make each button locate itself in the buttons list.

from tkinter import *
import random

class App(Tk):
    def __init__(self):
        Tk.__init__(self)

        self.totalButtons = random.randint(5, 25)

        # The buttons will be stored in a list
        self.buttons = []
        self.labels = []

        self.createButtons()

    def createButtons(self):
        for i in range(0, self.totalButtons):
            # Here I create a button and append it to the buttons list
            self.buttons.append(Button(self, text = i, command = self.removeButton))

            # Now I grid the last object created (the one we just created)
            self.buttons[-1].grid(row = i + 1, column = 1)

            # Same thing for the label
            self.labels.append(Label(self, text = i))
            self.labels[-1].grid(row = i + 1, column = 0)

    def removeButton(self):
        # When a button is clicked, buttonIndex should be able to find the index position of that button in self.buttons
        # For now I set it to 0, which will always remove the first (top) button
        indexPosition = 0

        # Takes the button (in this case, the first one) off the grid
        self.buttons[indexPosition].grid_forget()

        # Removes that button from self.buttons
        del self.buttons[indexPosition]

        # Same for the label
        self.labels[indexPosition].grid_forget()
        del self.labels[indexPosition]


def main():
    a = App()
    a.mainloop()

if __name__ == "__main__":
    main()

Thanks!

Upvotes: 2

Views: 426

Answers (1)

Steven Summers
Steven Summers

Reputation: 5384

command = lambda idx=i: self.removeButton(idx)

lambda here is taking the value i from your range and assigning it to idx and passing into the function. This function call is now unique to each button and so they have a value corresponding to their index.

for i, btn in enumerate(self.buttons):
    btn['command'] = lambda idx=i: self.removeButton(idx)

Because you are deleting each button from the list you need to assign a new value to the command parameter to properly reflect where the new position of the existing buttons in the list are.

    def createButtons(self):
        for i in range(0, self.totalButtons):
            # Here I create a button and append it to the buttons list
            self.buttons.append(Button(self, text = i, command = lambda idx=i: self.removeButton(idx)))

            # Now I grid the last object created (the one we just created)
            self.buttons[-1].grid(row = i + 1, column = 1)

            # Same thing for the label
            self.labels.append(Label(self, text = i))
            self.labels[-1].grid(row = i + 1, column = 0)

    def removeButton(self, i):
        # Takes the button at index i off the grid
        self.buttons[i].grid_forget()

        # Removes that button from self.buttons
        del self.buttons[i]

        # Same for the label
        self.labels[i].grid_forget()
        del self.labels[i]

        # Assign new values for index position
        for new_i, btn in enumerate(self.buttons):
            btn['command'] = lambda idx=new_i: self.removeButton(idx)

Upvotes: 2

Related Questions