How can I identify buttons, created in a loop?
<p>I am trying to program a minesweeper game on python using tkinter. I started off by creating a grid of buttons using a two dimensional list of 10x10. Then I created each button using a loop just so I don't have to manually create every single button and clip them on. </p>

<pre><code>self.b=[[0 for x in range(1,12)] for y in range(1,12)] #The 2 dimensional list
for self.i in range(1,11):
     for self.j in range(1,11):
            self.b[self.i][self.j]=tkinter.Button(root,text = ("     "),command = lambda: self.delete()) # creating the button
            self.b[self.i][self.j].place(x=xp,y=yp) # placing the button
            xp+=26 #because the width and height of the button is 26
        yp+=26
        xp=0
</code></pre>

<p>Basically I want the button to disappear upon being pressed. The problem is that I don't know how to let the program delete specifically the button that I pressed, as all the buttons are exactly the same. When creating the delete function:</p>

<pre><code>def delete(self):
    self.b[???][???].destroy()
</code></pre>

<p>I don't know how to let the program know which button it was that the user presses, so it can delete that specific one.</p>

<p><strong>The question:</strong>
Is there a way to let each button have something unique that allows it to be differentiated from the other buttons? Say assign each button a specific coordinate, so when button (2,3) is pressed, the numbers 2 and 3 are passed onto the delete function, so the delete function can delete button (2,3)?</p>

<p>While creating buttons in a loop, we <em>can</em> create (actually get) the unique identity. </p>

<p>For example: if we create a button:</p>

<pre><code>button = Button(master, text="text")
</code></pre>

<p>we can identify it immediately:</p>

<pre><code>print(button)
&gt; &lt;tkinter.Button object .140278326922376&gt;
</code></pre>

<p>If we store this identity into a list and asign a command to the button(s), linked to their index during creation, we can get their specific identity when pressed.</p>

<p>The only thing we have to to then is to fetch the button's identity by index, once the button is pressed.</p>

<p>To be able to set a command for the buttons <em>with the index as argument</em>, we use <code>functools</code>' <code>partial</code>.</p>

<h3>Simplified example (<code>python3</code>)</h3>

<p>In the simplified example below, we create the buttons in a loop, add their identities to the list (<code>button_identities</code>). The identity is fetched by looking it up with: <code>bname = (button_identities[n])</code>.</p>

<p>Now we have the identity, we can subsequently make the button do <em>anything</em>, including editing- or killing itself, since we have its identity.</p>

<p>In the example below, pressing the button will change its label to "clicked"</p>

<p><a href="http://i.stack.imgur.com/VJzVc.png" rel="nofollow"><img src="http://i.stack.imgur.com/VJzVc.png" alt="enter image description here"></a> </p>

<pre><code>from tkinter import *
from functools import partial

win = Tk()
button_identities = []

def change(n):
    # function to get the index and the identity (bname)
    print(n)
    bname = (button_identities[n])
    bname.configure(text = "clicked")

for i in range(5):
    # creating the buttons, assigning a unique argument (i) to run the function (change)
    button = Button(win, width=10, text=str(i), command=partial(change, i))
    button.pack()
    # add the button's identity to a list:
    button_identities.append(button)

# just to show what happens:
print(button_identities)

win.mainloop()
</code></pre>

<p>Or if we make it <em>destroy</em> the buttons once clicked:</p>

<p><a href="http://i.stack.imgur.com/QvUrU.png" rel="nofollow"><img src="http://i.stack.imgur.com/QvUrU.png" alt="enter image description here"></a></p>

<pre><code>from tkinter import *
from functools import partial

win = Tk()
button_identities = []

def change(n):
    # function to get the index and the identity (bname)
    print(n)
    bname = (button_identities[n])
    bname.destroy()

for i in range(5):
    # creating the buttons, assigning a unique argument (i) to run the function (change)
    button = Button(win, width=10, text=str(i), command=partial(change, i))
    button.place(x=0, y=i*30)
    # add the button's identity to a list:
    button_identities.append(button)

# just to show what happens:
print(button_identities)

win.mainloop()
</code></pre>

<h3>Simplified code for your matrix (python3):</h3>

<p>In the example below, I used <a href="https://docs.python.org/3/library/itertools.html#itertools.product" rel="nofollow">itertools's product()</a> to generate the coordinates for the matrix.</p>

<p><a href="http://i.stack.imgur.com/oyfyW.png" rel="nofollow"><img src="http://i.stack.imgur.com/oyfyW.png" alt="enter image description here"></a></p>

<pre><code>#!/usr/bin/env python3
from tkinter import *
from functools import partial
from itertools import product

# produce the set of coordinates of the buttons
positions = product(range(10), range(10))
button_ids = []

def change(i):
    # get the button's identity, destroy it
    bname = (button_ids[i])
    bname.destroy()

win = Tk()
frame = Frame(win)
frame.pack()

for i in range(10):
    # shape the grid
    setsize = Canvas(frame, width=30, height=0).grid(row=11, column=i)
    setsize = Canvas(frame, width=0, height=30).grid(row=i, column=11)

for i, item in enumerate(positions):
    button = Button(frame, command=partial(change, i))
    button.grid(row=item[0], column=item[1], sticky="n,e,s,w")
    button_ids.append(button)

win.minsize(width=270, height=270)
win.title("Too many squares")
win.mainloop()
</code></pre>

<h3>More options, destroying a button by coordinates</h3>

<p>Since <code>product()</code> also produces the x,y coordinates of the button(s), we can additionally store the coordinates (in <code>coords</code> in the example), and identify the button's identity by coordinates.</p>

<p>In the example below, the function <code>hide_by_coords():</code> destroys the button by coordinates, which can be useful in <code>minesweeper</code> -like game. As an example, clicking one button als destroys the one on the right:</p>

<pre><code>#!/usr/bin/env python3
from tkinter import *
from functools import partial
from itertools import product

positions = product(range(10), range(10))
button_ids = []; coords = []

def change(i):
    bname = (button_ids[i])
    bname.destroy()
    # destroy another button by coordinates
    # (next to the current one in this case)
    button_nextto = coords[i]
    button_nextto = (button_nextto[0] + 1, button_nextto[1])
    hide_by_coords(button_nextto)

def hide_by_coords(xy):
    # this function can destroy a button by coordinates
    # in the matrix (topleft = (0, 0). Argument is a tuple
    try:
        index = coords.index(xy)
        button = button_ids[index]
        button.destroy()
    except (IndexError, ValueError):
        pass

win = Tk()
frame = Frame(win)
frame.pack()

for i in range(10):
    # shape the grid
    setsize = Canvas(frame, width=30, height=0).grid(row=11, column=i)
    setsize = Canvas(frame, width=0, height=30).grid(row=i, column=11)

for i, item in enumerate(positions):
    button = Button(frame, command=partial(change, i))
    button.grid(column=item[0], row=item[1], sticky="n,e,s,w")
    button_ids.append(button)
    coords.append(item)

win.minsize(width=270, height=270)
win.title("Too many squares")
win.mainloop()
</code></pre>

python tkinter minesweeper