57

Something like this, would make the widget appear normally:

Label(self, text = 'hello', visible ='yes') 

While something like this, would make the widget not appear at all:

Label(self, text = 'hello', visible ='no') 
martineau
  • 119,623
  • 25
  • 170
  • 301
rectangletangle
  • 50,393
  • 94
  • 205
  • 275

8 Answers8

77

You may be interested by the pack_forget and grid_forget methods of a widget. In the following example, the button disappear when clicked

from Tkinter import *

def hide_me(event):
    event.widget.pack_forget()

root = Tk()
btn=Button(root, text="Click")
btn.bind('<Button-1>', hide_me)
btn.pack()
btn2=Button(root, text="Click too")
btn2.bind('<Button-1>', hide_me)
btn2.pack()
root.mainloop()
martineau
  • 119,623
  • 25
  • 170
  • 301
luc
  • 41,928
  • 25
  • 127
  • 172
  • 54
    `grid_remove` is another option. It's advantage over `grid_forget` is that grid will remember all of the options, so that a simple `grid()` will put it right back. There is no `pack_remove`. – Bryan Oakley Apr 22 '12 at 12:52
  • @BryanOakley:[Here](http://effbot.org/tkinterbook/pack.htm#Tkinter.Pack.pack_forget-method) it says that even `pack()` remembers it as well. – Alok Apr 30 '14 at 07:02
  • 1
    @shaktimaan: I don't see where it says the options are remembered. It can be redisplayed, but it might not be redisplayed in the same spot. – Bryan Oakley Apr 30 '14 at 10:45
  • 1
    what is `` – Pyd Mar 17 '18 at 16:27
  • @pyd It is the left mouse button, but I don't think it's necessary to use `bind` at all. – Bryan Zeng Jun 16 '18 at 00:29
  • How to bring it back after you've hidden it using `pack_forget()`? – Zaid Khan Jan 22 '19 at 04:51
  • 2
    @Bateman: You can bring it back by calling `pack()` again (assuming you've kept a reference to the widget). This is because `pack_forget()` just makes the widget disappear, but it still exists. – martineau May 09 '19 at 18:52
43

One option, as explained in another answer, is to use pack_forget or grid_forget. Another option is to use lift and lower. This changes the stacking order of widgets. The net effect is that you can hide widgets behind sibling widgets (or descendants of siblings). When you want them to be visible you lift them, and when you want them to be invisible you lower them.

The advantage (or disadvantage...) is that they still take up space in their master. If you "forget" a widget, the other widgets might readjust their size or orientation, but if you raise or lower them they will not.

Here is a simple example:

import Tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.frame = tk.Frame(self)
        self.frame.pack(side="top", fill="both", expand=True)
        self.label = tk.Label(self, text="Hello, world")
        button1 = tk.Button(self, text="Click to hide label",
                           command=self.hide_label)
        button2 = tk.Button(self, text="Click to show label",
                            command=self.show_label)
        self.label.pack(in_=self.frame)
        button1.pack(in_=self.frame)
        button2.pack(in_=self.frame)

    def show_label(self, event=None):
        self.label.lift(self.frame)

    def hide_label(self, event=None):
        self.label.lower(self.frame)

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • 6
    I could be wrong, but I don't think this works in Python/Tkinter. Guessing from your use of `raise()`, which is a Python reserved word (it's actually called `lift()`), I don't think you use Python/Tkinter. – AndyL Nov 09 '11 at 00:02
  • 12
    @AndyL: I use tkinter quite a lot these days (circa 2011) and have about 15 years experience with tk which translates over nicely. Frankly, I think you are wrong about this solution not working but I would love to hear your reasoning. Why do you say you don't think it works? Do you know of a case where this is so, or are you guessing? Thanks, by the way, for the reminder about lift versus raise. I sometimes forget that tkinter has to stray from tk's native api to accomodate the syntax of python, and lift is one command I very rarely need to use. I've updated my answer. – Bryan Oakley Nov 09 '11 at 00:19
  • 11
    After re-reading my comment, I'd like to say that I definitely didn't mean to be as offensive as I sounded. My apologies. I made my initial comment because I've tried your solution before and couldn't get it to work for me. I got a TclError whenever I tried to lower a widget behind its parent. This could very conceivably be a lapse on my own part. Could you provide code to enlighten me? – AndyL Nov 09 '11 at 01:34
  • 14
    @AndyL: My mistake. In looking back at my answer I see I worded the solution incorrectly. You are right that you can't hide a widget behind its parent, but you can hide it behind other widgets. I've updated my answer and included an example. Thanks for bringing this to my attention. – Bryan Oakley Nov 09 '11 at 02:40
  • 48
    +1 for a perfect example how to handle misunderstandings ;-) It's nice to see, that there are still polite and reasonable people left on earth – Don Question Nov 17 '12 at 01:31
5

I know this is a couple of years late, but this is the 3rd Google response now for "Tkinter hide Label" as of 10/27/13... So if anyone like myself a few weeks ago is building a simple GUI and just wants some text to appear without swapping it out for another widget via "lower" or "lift" methods, I'd like to offer a workaround I use (Python2.7,Windows):

from Tkinter import *


class Top(Toplevel):
    def __init__(self, parent, title = "How to Cheat and Hide Text"):
        Toplevel.__init__(self,parent)
        parent.geometry("250x250+100+150")
        if title:
            self.title(title)
        parent.withdraw()
        self.parent = parent
        self.result = None
        dialog = Frame(self)
        self.initial_focus = self.dialog(dialog)
        dialog.pack()


    def dialog(self,parent):

        self.parent = parent

        self.L1 = Label(parent,text = "Hello, World!",state = DISABLED, disabledforeground = parent.cget('bg'))
        self.L1.pack()

        self.B1 = Button(parent, text = "Are You Alive???", command = self.hello)
        self.B1.pack()

    def hello(self):
        self.L1['state']="normal"


if __name__ == '__main__':
    root=Tk()   
    ds = Top(root)
    root.mainloop()

The idea here is that you can set the color of the DISABLED text to the background ('bg') of the parent using ".cget('bg')" http://effbot.org/tkinterbook/widget.htm rendering it "invisible". The button callback resets the Label to the default foreground color and the text is once again visible.

Downsides here are that you still have to allocate the space for the text even though you can't read it, and at least on my computer, the text doesn't perfectly blend to the background. Maybe with some tweaking the color thing could be better and for compact GUIs, blank space allocation shouldn't be too much of a hassle for a short blurb.

See Default window colour Tkinter and hex colour codes for the info about how I found out about the color stuff.

Community
  • 1
  • 1
4

I'm also extremely late to the party, but I'll leave my version of the answer here for others who may have gotten here, like I did, searching for how to hide something that was placed on the screen with the .place() function, and not .pack() neither .grid().

In short, you can hide a widget by setting the width and height to zero, like this:

widget.place(anchor="nw", x=0, y=0, width=0, height=0)

To give a bit of context so you can see what my requirement was and how I got here. In my program, I have a window that needs to display several things that I've organized into 2 frames, something like this:

[WINDOW - app]
  [FRAME 1 - hMainWndFrame]
    [Buttons and other controls (widgets)]
  [FRAME 2 - hJTensWndFrame]
    [other Buttons and controls (widgets)]

Only one frame needs to be visible at a time, so on application initialisation, i have something like this:

hMainWndFrame = Frame(app, bg="#aababd")
hMainWndFrame.place(anchor="nw", x=0, y=0, width=480, height=320)
...
hJTensWndFrame = Frame(app, bg="#aababd")

I'm using .place() instead of .pack() or .grid() because i specifically want to set precise coordinates on the window for each widget. So, when i want to hide the main frame and display the other one (along with all the other controls), all i have to do is call the .place() function again, on each frame, but specifying zero for width and height for the one i want to hide and the necessary width and height for the one i want to show, such as:

hMainWndFrame.place(anchor="nw", x=0, y=0, width=0, height=0)
hJTensWndFrame.place(anchor="nw", x=0, y=0, width=480, height=320)

Now it's true, I only tested this on Frames, not on other widgets, but I guess it should work on everything.

Vasim Hayat
  • 909
  • 11
  • 16
AdrianNULL
  • 41
  • 2
2

For hiding a widget you can use function pack_forget() and to again show it you can use pack() function and implement them both in separate functions.

from Tkinter import *
root = Tk()
label=Label(root,text="I was Hidden")
def labelactive():
    label.pack()
def labeldeactive():
    label.pack_forget()
Button(root,text="Show",command=labelactive).pack()
Button(root,text="Hide",command=labeldeactive).pack()
root.mainloop()
Saheb Singh
  • 1,172
  • 7
  • 13
2

I was not using grid or pack.
I used just place for my widgets as their size and positioning was fixed.
I wanted to implement hide/show functionality on frame.
Here is demo

from tkinter import *
window=Tk()
window.geometry("1366x768+1+1")
def toggle_graph_visibility():
    graph_state_chosen=show_graph_checkbox_value.get()
    if graph_state_chosen==0:
        frame.place_forget()
    else:
        frame.place(x=1025,y=165)
score_pixel = PhotoImage(width=300, height=430)
show_graph_checkbox_value = IntVar(value=1)
frame=Frame(window,width=300,height=430)
graph_canvas = Canvas(frame, width = 300, height = 430,scrollregion=(0,0,300,300))
my_canvas=graph_canvas.create_image(20, 20, anchor=NW, image=score_pixel)
vbar=Scrollbar(frame,orient=VERTICAL)
vbar.config(command=graph_canvas.yview)
vbar.pack(side=RIGHT,fill=Y)
graph_canvas.config(yscrollcommand=vbar.set)
graph_canvas.pack(side=LEFT,expand=True,fill=BOTH)
frame.place(x=1025,y=165)
Checkbutton(window, text="show graph",variable=show_graph_checkbox_value,command=toggle_graph_visibility).place(x=900,y=165)
window.mainloop()

Note that in above example when 'show graph' is ticked then there is vertical scrollbar.
Graph disappears when checkbox is unselected.
I was fitting some bar graph in that area which I have not shown to keep example simple.
Most important thing to learn from above is the use of frame.place_forget() to hide and frame.place(x=x_pos,y=y_pos) to show back the content.

user1371666
  • 445
  • 1
  • 5
  • 18
0

For someone who hate OOP like me (This is based on Bryan Oakley's answer)

import tkinter as tk

def show_label():
    label1.lift()

def hide_label():
    label1.lower()

root = tk.Tk()
frame1 = tk.Frame(root)
frame1.pack()

label1 = tk.Label(root, text="Hello, world")
label1.pack(in_=frame1)

button1 = tk.Button(root, text="Click to hide label",command=hide_label)
button2 = tk.Button(root, text="Click to show label", command=show_label)
button1.pack(in_=frame1)
button2.pack(in_=frame1)

root.mainloop()
bemygon
  • 83
  • 8
0
import tkinter as tk
...
x = tk.Label(text='Hello', visible=True)
def visiblelabel(lb, visible):
    lb.config(visible=visible)
visiblelabel(x, False)  # Hide
visiblelabel(x, True)  # Show

P.S. config can change any attribute:

x.config(text='Hello')  # Text: Hello
x.config(text='Bye', font=('Arial', 20, 'bold'))  # Text: Bye, Font: Arial Bold 20
x.config(bg='red', fg='white')  # Background: red, Foreground: white

It's a bypass of StringVar, IntVar etc.

wyz23x2
  • 298
  • 4
  • 16
  • 1
    config method does not provide the "visible" argument. Did you even test your code? I did not test it on Python2 but there's no hint of "visible" in docs. `_tkinter.TclError: unknown option "-visible"` – sausix May 23 '20 at 18:03