0

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.

  • Does this answer your question? [get the `Button['text']` on click](https://stackoverflow.com/a/55735566/7414759) – stovfl May 24 '20 at 11:05

2 Answers2

0

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

Mandera
  • 2,647
  • 3
  • 21
  • 26
  • 1
    Typically you wouldn't use `bind` for a button. The button has a `command` option for assigning functionality to a button. – Bryan Oakley May 24 '20 at 12:54
  • Ah you're right, but I'm assuming that the `command` option is just a shortcut to do a bind, so I thought I'd try to teach a general solution for any widget instead of only with buttons. But for this question it'd probably be better to have an answer only using the `command` option, you're right. – Mandera May 24 '20 at 13:02
  • it does more than just binding to a button click. It handles button press, button release, and also invoking the button via the keyboard. – Bryan Oakley May 24 '20 at 14:15
  • Oh okay! That's interesting, is there anywhere I can find more information about that? – Mandera May 24 '20 at 14:39
0

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())
Paul M.
  • 10,481
  • 2
  • 9
  • 15