Lukas
Lukas

Reputation: 5

How do I destroy specific button in the loop when clicked?

I am trying to create a 10*10 board of buttons, which when clicked, the clicked button is destroyed and only that one. However, I don't know how to specify which button has been clicked.

from tkinter import *

root = Tk()
root.title("Board")
def buttonClick():
    button.destroy()


for i in range(10):
    for j in range(10):
        button = Button(root, text="", padx=20, pady=10, command=buttonClick)
        button.grid(row=i+1, column=j+1)

root.mainloop()

Upvotes: 0

Views: 80

Answers (2)

furas
furas

Reputation: 143097

You have to create function which gets widget/button as argument and uses it with destroy()

def buttonClick(widget):
    widget.destroy()

And first you have to create Button without command=

button = tk.Button(root, text="", padx=20, pady=10)

and later you can use this button as argument in command=.

button["command"] = lambda widget=button:buttonClick(widget) 

It needs to use lambda to assign function with argument.

Because you create many buttons in loop so it also needs to use widget=button in lambda to create unique variable with value from button for every command. If you don't use it then all commands will use reference to the same (last) button - and click on every button will destroy only last button.


Full working code

import tkinter as tk  # PEP8: `import *` is not preferred

# --- functions ---

def buttonClick(widget):
    widget.destroy()

# --- main ---

root = tk.Tk()
root.title("Board")

for i in range(10):
    for j in range(10):
        button = tk.Button(root, text="x", padx=20, pady=10)
        button["command"] = lambda widget=button:buttonClick(widget)
        button.grid(row=i+1, column=j+1)

root.mainloop()

PEP 8 -- Style Guide for Python Code

Upvotes: 2

Rolv Apneseth
Rolv Apneseth

Reputation: 2118

This can be easily accomplished with a custom class if you're alright with that:

from tkinter import Button, Tk


root = Tk()
root.title("Board")


class Self_Destruct_Button(Button):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.configure(command=self.button_click)

    def button_click(self):
        self.destroy()


for i in range(10):
    for j in range(10):
        button = Self_Destruct_Button(root, text="", padx=20, pady=10)
        button.grid(row=i + 1, column=j + 1)

root.mainloop()

So the custom class just assigns the command to a button_click method, which destroys the button.

As a side note, I also removed the wildcard import as that's not best practice.

Let me know if this works for you

Upvotes: 2

Related Questions