Sof
Sof

Reputation: 59

change button text, using button name

I have an issue, I created a table of buttons using a loop, and I saved the button's names in a list, now I want to change the text of the buttons when one button is clicked. I don't konw how.

this is the loop where i create the table

     def grid(n):
                i = n*n
                for widget in LeftFrame.winfo_children():
                    widget.destroy()
                for i in range(n):
                    for row in range(n):
                        for col in range(n):
                            button = Button(LeftFrame, text=' ', width=12, height=6, command=lambda: checker(button, i))
                            button.grid(row=row, column=col)
                            button_identities.append(button)

and this is the function on click of the button

        def checker(buttons, i):
            print(i)
            global click, button_identities
            print(button_identities)
            bname = (button_identities[i])
            print(bname)
            if buttons["text"] == ' ' and click == True:
                buttons["text"] = 'X'
                click = False
                # scorekeeper()
            elif buttons['text'] == ' ' and click == False:
                buttons['text'] = 'O'
                click = True
                # scorekeeper()

there is a method to check the text from the button name in the last function

Upvotes: 0

Views: 373

Answers (2)

Matiiss
Matiiss

Reputation: 6156

so this is my take on this issue:

from tkinter import Tk, Button


root = Tk()


class EditableButton(Button):
    def __init__(self, parent, row, col):
        Button.__init__(self, parent)
        self.parent = parent
        self.row = row
        self.col = col
        self.tracker = 0
        self.name_list = ['apple', 'pear']
        print(len(self.name_list))

        self.button = Button(self.parent, text=self.name_list[self.tracker], command=self.change_text)
        self.button.grid(row=self.row, column=self.col)

    def change_text(self):
        if self.tracker < len(self.name_list) - 1:
            self.tracker += 1
        else:
            self.tracker = 0
        self.button.config(text=self.name_list[self.tracker])


n = 3
for row in range(n):
    for col in range(n):
        button = EditableButton(root, row, col)

root.mainloop()

basically what happens is You make a class that is like a template for buttons and each class object created by the loop is independent, each of them has their own spot in memory, so whenever You press the button it only calls the function in its own class

Upvotes: 0

TheLizzard
TheLizzard

Reputation: 7680

Try this:

from functools import partial

def grid(n):
    for widget in LeftFrame.winfo_children():
        widget.destroy()
    for i in range(n):
        for row in range(n):
            for col in range(n):
                button = Button(LeftFrame, text=' ', width=12, height=6)
                # Assign the button a command
                command = partial(checker, button)
                button.config(command=command)

                button.grid(row=row, column=col)
                button_identities.append(button)

def checker(button):
    # The argument is a button
    global click

    # If the cell is empty
    if button.cget("text") == " ":
        # If Xs are you play
        if click:
            # Change the text of the button
            button.config(text="X")
            click = False
        # If Os are to play
        else:
            # Change the text of the button
            button.config(text="O")
            click = True

I usually use <widget>.cget("<parameter>") to get the parameter out of a widget and <widget>.config(parameter=<new value>) to assign it a new value. Also you can use functools.partial to pass in arguments for the button command.

Upvotes: 1

Related Questions