Tkinter removing a button from a running program

23,829

Solution 1

self.call_button is set to the result of grid(row=5, column=5) and not to the Button..

from tkinter import *
class App(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        self.grid()
        self.a()

    def a(self):
        self.call_button = Button(self, text = "Call", command=self.b)
        self.call_button.grid(row=5, column=5) # This is fixing your issue

    def b(self):
        self.call_button.destroy()

root = Tk()
app = App(master=root)
app.mainloop()

Solution 2

In python, if you do foo=a().b(), foo is given the value of b(). So, when you do self.call_button = Button(...).grid(...), self.call_button is given the value of .grid(...), which is always None.

if you want to keep a reference to a widget, you need to separate your widget creation from your widget layout. This is a good habit to get into, since those are conceptually two different things anyway. In my experience, layout can change a lot during development, but the widgets I use don't change that much. Separating them makes development easier. Plus, it opens the door for later if you decide to offer multiple layouts (eg: navigation on the left, navigation on the right, etc).

Share:
23,829
Shay
Author by

Shay

Updated on July 17, 2020

Comments

  • Shay
    Shay almost 4 years

    I was trying to create a function that creates and places a button on the screen (with grid) and the button's command would be removing itself (or any other widget) but I've failed to do so.

    def a(self):
        self.call_button = Tkinter.Button(self.root, text = "Call", command=self.b).grid(row = 5, column = 5)
    
    def b(self):
        self.call_button.destroy()
    

    a creates the button and b removes it, but when i call on b it says "NoneType object has no attribute destroy"

    How do I go about doing this correctly?