5

I want to hide a tkinter button but not when the user clicks it. I just want to hide it, at random times. How will I do that in Python? Below is the code I tried:

self.startGame = Button(self.canvas, text="Start", background='white', command = self.startGame, font=("Helvetica"))
self.startGame.place(x=770, y=400)

Hiding it:

 self.startGame.bind('<Button-1>', self.hide_me)

 def hide_me(self, event):
    print('hide me')
    event.widget.pack_forget()

It doesn't even get inside the hide_me function.

martineau
  • 119,623
  • 25
  • 170
  • 301
alyssaeliyah
  • 2,214
  • 6
  • 33
  • 80
  • 6
    `.pack_forget()` isn't going to do anything to a widget that wasn't originally made visible by `.pack()`. You need to use `.place_forget()` instead. – jasonharper Nov 12 '18 at 05:36
  • Your button name self.startGame and also it links to a function called self.startGame. This may be why it does not make it to hide_me. answer from jasonharper above explains about what hide_me won't do once you get to reach it. –  Nov 13 '18 at 09:40
  • @DaveMaheux where the command is just linking back to the button this is not actually stopping the `bind()` from activating `hid_me`. This code will work when they change `pack_forget()` to `place_forget()`. However I do agree that `command=self.startGame` is wrong here. – Mike - SMT Nov 13 '18 at 17:29

1 Answers1

5

As pointed out in the comments you should use place_forget() for widgets that were set on the screen using place().

Same goes for pack() and grid(). You would use pack_forget() and grid_forget() respectively.

Here is a modified example of your code.

import tkinter as tk

class Example(tk.Tk):
    def __init__(self):
        super().__init__()
        canvas = tk.Canvas(self)
        canvas.pack()
        self.startGame = tk.Button(canvas, text="Start", background='white', font=("Helvetica"))
        self.startGame.place(x=150, y=100)
        self.startGame.bind('<Button-1>', self.hide_me)

    def hide_me(self, event):
        print('hide me')
        event.widget.place_forget()

if __name__ == "__main__":
    Example().mainloop()

That said you do not need a bind here. Simply use a lambda statement in your command like this:

import tkinter as tk

class Example(tk.Tk):
    def __init__(self):
        super().__init__()
        canvas = tk.Canvas(self)
        canvas.pack()
        self.startGame = tk.Button(canvas, text="Start", background='white', font=("Helvetica"),
                                   command=lambda: self.hide_me(self.startGame))
        self.startGame.place(x=150, y=100)

    def hide_me(self, event):
        print('hide me')
        event.place_forget()

if __name__ == "__main__":
    Example().mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • 1
    How about showing it again? What is the corresponding code for it? – alyssaeliyah Nov 15 '18 at 00:29
  • 5
    @Eliyah I believe for all geometry managers if you simply call `place()` on the widget it will be placed back on the window where it was before. Same for `grid()` and `pack()`. – Mike - SMT Nov 15 '18 at 00:30
  • Doesn't seem to be the case, at least for `pack`. It's placed at the end of widget list (e.g. at the bottom) – Osman-pasha Apr 06 '21 at 09:25
  • 1
    @Osman-pasha `pack()` is a bit different because it does not have a defined location like place and grid. – Mike - SMT Apr 06 '21 at 14:08