Frostyfeet909
Frostyfeet909

Reputation: 135

How to hide individual widgets created by a loop in python

I'm trying to grid_forget() a specific button created by the for loop, I can individually reference which button is which however I am unable to refer to individual buttons to 'forget' them (and then replace them with labels although this is not included in the question).

So does anybody have any idea on how to reference individual buttons created by a loop and subsequently hide the widget?

Code

#Importing modules
from tkinter import*

#Defining global variables
root = Tk()


class GUI():
    #Class for all widgets
    def __init__(self):
        #Sets up nothing
        pass

    def create_button(self, info, boom, posit):
        #Creates buttons
        self.button = Button(root)
        self.button.config(text=info)
        self.button.config(command=boom)
        self.button.grid(column=posit[0],row=posit[1])

    def create_label(self, info, posit):
        #Creates labels
        self.label = Label(root)
        self.label.config(text=info)
        self.label.grid(column=posit[0],row=posit[1])

    def go_away(self):
        #Makes buttons disappear
        #self.button.grid_forget()
        self.button.destroy()

    def come_back(self):
        #Makes buttons reappear
        self.button.grid()

    def user_input(self,row,column):
        print("Row:", row)
        print("Column:", column)
        self.configure(row,column)
        print(self.button)

    def create_board(self):
        for x in range(3):
            for y in range(3):
                cmd = lambda row=y, column=x: self.user_input(row,column)
                self.create_button("   ", cmd, [x,y])

class Board(GUI):
    def __init__(self):
        self.create_board()
        self.create_label("Hey",[3,0])
        self.board = ["x", "x", "O", "O", "O", "O", "O", "O", "O"]

        row1 = [self.board[0],self.board[1],self.board[2]]
        row2 = [self.board[3],self.board[4],self.board[5]]
        row3 = [self.board[6],self.board[7],self.board[8]]

        colum1 = [self.board[0],self.board[3],self.board[6]]
        colum2 = [self.board[1],self.board[4],self.board[7]]
        colum3 = [self.board[2],self.board[5],self.board[8]]
    
        self.rows = [row1,row2,row3]
        self.colums = [colum1,colum2,colum3]

    def configure(self,row,column):
        self.rows[row][column] = "O"
        self.board = []
        for row in self.rows:
            for position in row:
                self.board.append(position)
    
nodes = GUI()
board = Board()
root.mainloop()

Upvotes: 0

Views: 540

Answers (2)

Terry Jan Reedy
Terry Jan Reedy

Reputation: 19144

One way or another you have to keep a reference to each widget that you want to refer to later. create button rebinds self.button to each button in turn, losing the reference to previous buttons. Instead, create_board should create a 3 x 3 array of buttons. Something like (untested)

def create_board(self):
    self.board = []
    for y in range(3):  # row
        row = []
        for x in range(3):  # column
            mycmd = lambda row=y, column=x: self.user_input(row,column)
            button = Button(root, text="   ", cmd=mycmd)
            button.grid(row = y, column = x)
            row.append(button)
        self.board.append(row)

Upvotes: 1

user4171906
user4171906

Reputation:

Typically a class contains all the methods for a given object, so you would create an instance of GUI for each button, and the GUI (instance) would contain the create, destroy, bring back, etc. functions for that button alone, although you can not bring back a button because you destroy it, not forget it, (and also have no way to tell the class to bring the button back). The code below illustrates creating and destroying the buttons in a simplified way.

from Tkinter import*

root = Tk()


class GUI():
    def __init__(self, root, x, y):
        self.root=root
        self.create_button(x, y)

    def create_button(self, x, y):
        #Creates buttons
        self.button = Button(root)
        self.button.config(text="%s-%s" % (x, y))
        self.button.config(command=self.go_away)
        self.button.grid(column=x,row=y)

    def create_label(self, info, posit):
        #Creates labels
        self.label = Label(root)
        self.label.config(text=info)
        self.label.grid(column=posit[0],row=posit[1])

    def go_away(self):
        #Makes buttons disappear
        #self.button.grid_forget()
        self.button.destroy()

    def come_back(self):
        #Makes buttons reappear
        self.button.grid()

    def user_input(self,row,column):
        print("Row:", row)
        print("Column:", column)
        self.configure(row,column)
        print(self.button)


class Board():
    def __init__(self):
        self.buttons=[]
        self.create_board()
        Label(root, text="click on a button\nto destroy it",
              bg="lightblue"). grid(row=10, column=0,
              columnspan=3, sticky="nsew")

    def create_board(self):
        for x in range(3):
            for y in range(3):
                self.buttons.append(GUI(root, x, y))
##                cmd = lambda row=y, column=x: self.user_input(row,column)
##                self.create_button("   ", cmd, [x,y])

board = Board()
root.mainloop()

Upvotes: 2

Related Questions