Python/TkInter - Method to find which button was pressed out of a grid of buttons made by a for loop

593 Views Asked by At

I'm trying to make a very simple Othello iteration with Tkinter and Python and have an idea however I don't know a method to retrieve which button is pressed (through an integer?). I have a made a grid of buttons using

for x in range(8):
    for y in range(8):
        btn = Button(frame)
        buttons.append(btn)
        btn.grid(column=x, row=y, sticky=N+S+E+W)
        btn.config(bg='green2')

I'm planning to config buttons on press and check all 8 directions by adding and subtracting the values of the buttons to find the button the the left (-8), upper right (+7), etc. I'm very new to coding and would like any feedback, thank you.

2

There are 2 best solutions below

4
On

Welcome to SO!

You can create a bind on any widget in tkinter, the syntax is:

widget.bind(sequence, func, add)

So for your example you could create a bind for each button and pass the x and y values are arguments to keep track of which button is which in the target function. Something like this:

btn.bind("<Button-1>", lambda x=x, y=y: print(x, y))

This will print the coordinate of each button in the grid, you can then replace the print statement with whatever function you'd like.

A list of all binds can be found here

0
On

You don't have to wrap your entire application in a class like I've done, or even have a static method. The critical thing is that you have some kind of callback function that gets triggered when a button is pressed. As part of that callback function invokation, you also pass a reference of the button object that was pressed into the callback. There are other ways of doing this, but I think it makes the most sense to pass a reference to the button itself:

import tkinter as tk


class Application(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.title("Buttons")
        self.resizable(width=False, height=False)

        number_of_rows = 8
        number_of_columns = 8

        for y in range(number_of_rows):
            for x in range(number_of_columns):
                button = tk.Button(self, text=f"{x}, {y}")
                button.config(command=lambda button=button: Application.on_button_click(button))
                button.grid(column=x, row=y)

    @staticmethod
    def on_button_click(button):
        button.config(bg="green")
        print(f"You clicked on {button['text']}")


def main():

    application = Application()
    application.mainloop()

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())