pythontkinterturtle-graphicspython-turtle

Distinguishing callbacks for different events when using the same function


I am coding minesweeper in python turtle. I have made it generate 10x10 button layout using this script:

position_x = -400
position_y = -200
number_colum = 0
rows_buttons = []
for i in range(10):
    for i in range(10):
        rows_buttons.append([tk.Button(canvas.master, text="////", command=button_run)])
        canvas.create_window(position_x, position_y, window=rows_buttons[number_colum])
        number_colum += 1
        position_x += 40
    position_y += 40
    position_x += -400

However I am having trouble finding out which button was pressed (e.g. button at (2,3)). How can I code it so it's able to tell which one is which?

Here is the full code:

import random
import turtle
import tkinter as tk

screen=turtle.Screen() 
screen.bgcolor("light blue") 
screen.setup(1.0,1.0) 
screen.title("Turtle minesweeper")
canvas = screen.getcanvas()


def button_run():
    pass



position_x = -400
position_y = -200
number_colum = 0
rows_buttons = []
for i in range(10):
    for i in range(10):
        rows_buttons.append([tk.Button(canvas.master, text="////", command=button_run)])
        canvas.create_window(position_x, position_y, window=rows_buttons[number_colum])
        number_colum += 1
        position_x += 40
    position_y += 40
    position_x += -400

rows = []
for i in range(10):
    rows.append([0,0,0,0,0,0,0,0,0,0])

rows_descovered = []
for i in range(10):
    rows.append([0,0,0,0,0,0,0,0,0,0])

mines_maker = 10
while not mines_maker == 0:
    random_row_number = random.randint(0,9)
    random_colum_number = random.randint(0,9)
    random_row = rows[random_row_number]
    random_colum = random_row[random_colum_number]

    if random_row[random_colum] == 0:
        random_row[random_colum_number] = 1
        rows[random_row_number] = random_row
        mines_maker -= 1
    else:
      pass

I can't add variables at the end of the function, and I wish to not use mouse coordinates as it is just janky for me.


Solution

  • To reuse the same function for callbacks, functions must be used with default arguments. This is to ensure that the value used by the caller is a constant. If default arguments aren't used, Python will load the values for the variables at runtime, which will be a static value (since the loop has finished execution).

    Here is a MWE. Note the command passed to the button uses a default argument.

    #!/usr/bin/python3
    import tkinter as tk
    
    
    def callback(x, y):
        print("Hello from ({}, {})!".format(x, y))
    
    root = tk.Tk()
    for i in range(10):
        for j in range(10):
            tk.Button(text="{}, {}".format(i, j),
                      command=lambda x=i, y=j: callback(x, y))\
                      .grid(column=i, row=j)
    
    root.mainloop()