I'm making a very simple python programming using tkinter. I want to draw some rectangles on a canvas and then when one clicks on a certain rectangle, show the tags of that rectangle. I can't get it to work. The problem seems to be that wherever I click on the canvas, the function get_closest returns 1. Any help is appreciated. This is my first time working with tkinter (and python for that matter), so any remarks about my code that aren't linked to the problems itself, are welcome as well!
import tkinter as tk
myrecs = [[None for j in range(4)] for i in range(4)]
class application:
def __init__(self, parent):
self.parent = parent
self.frame = tk.Frame(self.parent)
self.frame.grid(row=0)
self.quitbutton = tk.Button(self.frame, text = "Quit", command = lambda:quit())
self.quitbutton.grid(row=0, column = 0, sticky=tk.W + tk.E)
self.canvas = tk.Canvas(self.frame, width=200, height=200, bg = "blue")
self.canvas.bind("<ButtonPress-1>", self.buttonclick)
self.canvas.grid(row=1, columnspan = 2)
self.tag = self.canvas.create_text(10, 150, text="", anchor="nw")
self.makebutton = tk.Button(self.frame, text = "Make nice canvas", command = self.makecanvas)
self.makebutton.grid(row=0, column = 1, sticky = tk.W + tk.E)
def makecanvas(self):
for i in range(4):
for j in range(4):
myrecs[i][j] = self.canvas.create_rectangle(20*i, 20*j, 20*(i+1), 20*(j+1), tags=("rectangle", "i"+str(i), "j"+str(j)))
def buttonclick(self, event):
cnv = self.canvas
item = cnv.find_closest(cnv.canvasx(event.x), cnv.canvasy(event.y))[0]
tags = cnv.gettags(item)
cnv.itemconfigure(self.tag, text=tags[0])
if __name__ == "__main__":
root = tk.Tk()
root.title("Test")
app = application(root)
root.mainloop()
find_closest returns 1 means it's finding the very first element you created within the canvas, which in this case is the create_text.
Oddly enough, when you create_text with text="" it seems to be overtaking all your other elements. With a simple fix of text=" " it will now locate the closet rectangles on clicks.
With the other elements, when you assign option="" it actually disables (as far as I know) the option so instead of using its default values, you are actively telling tcl interpreter to not use it. This can be observed in other elements like create_rectangle(..., outline="") in which the default outline="black" will no longer apply, and you won't even get an outline. I have a feeling text="" yield a similar effect and for some reason basically covers the entire canvas area, so it causes find_closest to always return that element. Perhaps if you're lucky #BryanOakley (a tcl expert) can chime in on the backend reasoning.
In fact, if you tried find_above(item) you will notice that the text is consistently below your other elements drawn afterwards.
In short:
# Change this:
self.tag = self.canvas.create_text(10, 150, text="", anchor="nw")
# To this:
self.tag = self.canvas.create_text(10, 150, text=" ", anchor="nw")
Related
This is about moving a label on a canvas in Python 3.7 (I think) using tkinter.
There are lots of answers on Google and here on this site, but none of them have answered my question and yet I can't imagine my code couldbe much simpler. I'm not terribly experienced when it comes to Python and clearly I'm doing something fundamentally wrong.
What I want to do: move a label to a position on a canvas dictated by the click of a mouse.
Here we are:
root = tk.Tk()
root.geometry("800x600")
def ClickedCallback(event):
#print(f'Event: {event}, l2: {l2}, tags: {canvas.gettags()}')
canvas.move(l2, 5, 0)
canvas = tk.Canvas(root, width=1000, height=600, bg='blue')
canvas.bind("<Button-1>", ClickedCallback)
canvas.place(relwidth=0.9, relheight=0.8, relx = 0.05, rely = 0.05)
l2 = tk.Label(canvas, bg='red')
l2.bind("<Button-1>", ClickedCallback)
l2.place(relx=0.2, rely=0.2)
l2['text'] = "Test"
root.mainloop()
Now that causes a straight up error. "line 2591, in move
self.tk.call((self._w, 'move') + args)
_tkinter.TclError: invalid boolean operator in tag search expression"
I then saw an example that showed the object name entered into the method as a string rather than the object itself. So the line became:
canvas.move('l2', 5, 0)
Now this doesn't cause an error. But it also doesn't do anything.
I don't even know if moving on a canvas is the best way to do this. I just want to move a label around inside the window and this seemed to be the one that appeared in searches.
To place widget (ie. Label) on Canvas you have to use
label_id = canvas.create_window(position, window=l2,...)
not place()/grid()/pack()
And later you use this label_id to move it.
Simple example - Label is moved when you click Canvas
import tkinter as tk
# --- functions ---
def clicked_callback(event):
#canvas.move(label_id, 5, 0)
canvas.coords(label_id, event.x, event.y)
# --- main ---
root = tk.Tk()
root.geometry("800x600")
canvas = tk.Canvas(root, width=1000, height=600, bg='blue')
canvas.bind("<Button-1>", clicked_callback)
canvas.place(relwidth=0.9, relheight=0.8, relx=0.05, rely=0.05)
l2 = tk.Label(canvas, text="Test", bg='red')
#l2.bind("<Button-1>", clicked_callback)
label_id = canvas.create_window((100, 100), window=l2)
root.mainloop()
I have this bit of code in my Graduation-project-program...thing.
Extract:
[...]
rssfeed = tkinter.Frame(window, bg='black', width=200, height=80)
feed = feedparser.parse('http://www.repubblica.it/rss/homepage/rss2.0.xml')
feedShow = {'entries': [{feed['entries'][0]['title']}]}
class RSSDisplay(tkinter.Frame):[4]
def __init__(self, master=None, **kw):
tkinter.Frame.__init__(self, master=master, **kw)
self.txtHeadline = tkinter.StringVar()
self.headline = tkinter.Label(self, textvariable=self.txtHeadline,
bg='black', fg='white', font=("arial", 20))
self.headline.grid()
self.headlineIndex = 0
self.updateHeadline()
def updateHeadline(self):
try:
headline = feed['entries'][self.headlineIndex]['title']
except IndexError:
self.headlineIndex = 0
headline = feed['entries'][self.headlineIndex]['title']
self.txtHeadline.set(headline)
self.headlineIndex += 1
self.after(10000, self.updateHeadline)
[...]
RSSDisplay(window).place(x=340, y=500)
Now this displays the Headlines of my favorite newspaper ( La Repubblica, I'm Italian), which are updated every 10 seconds.
Since RSSDisplay(window).place(x=340, y=500)looks ugly beacause the text isn't centered, 'cause every sentence starts at said coordinates and not at the center for each entry in the Headlines, but always at x=340 and y=500.
I'd need it to be scrolling on top from left to right, instead of abruptly change.
If this isn't achieveable please point out to me under what conditions this could be done (i.e. changing Framework, GUI or language even thi I'd prefer to stick with Python).
If more information is needed please tell me and I'll try to add it.
Thanks everyone.
Here my take on a simple ticker: I use the tkinter.Text widget (http://effbot.org/tkinterbook/text.htm). In tick() I move the see() function of the text widget to advance one character of the news feed to the right.
Of course, this can be much improved on (for more versatile layouting you could try to use the tkinter.Canvas widget).
import feedparser
import tkinter as tk
feed = feedparser.parse('http://www.repubblica.it/rss/homepage/rss2.0.xml')
feedShow = {'entries': [{feed['entries'][0]['title']}]}
class RSSTicker(tk.Text):
def __init__(self, parent, **kw):
super().__init__(parent, height=1, wrap="none", state='disabled', **kw)
self.headlineIndex = 0
self.text = ''
self.pos = 0
self.after_idle(self.updateHeadline)
self.after_idle(self.tick)
def updateHeadline(self):
try:
self.text += '.....' + feed['entries'][self.headlineIndex]['title']
except IndexError:
self.headlineIndex = 0
self.text = feed['entries'][self.headlineIndex]['title']
self.headlineIndex += 1
self.after(10000, self.updateHeadline)
def tick(self):
if self.pos < len(self.text):
self.config(state='normal')
self.insert('end', self.text[self.pos])
self.pos += 1
self.see('end')
self.config(state='disabled')
self.after(300, self.tick)
if __name__ == '__main__':
root = tk.Tk()
ticker = RSSTicker(root, bg='black', fg='white', font=("arial", 20))
ticker.pack(side='top', fill='x')
root.mainloop()
Tkinter comes with different geometry managers of which I don't recommend place (not very flexible..). I am not exactly sure how you want your layout to look like. But you could try pack (besides pack there is also grid):
RSSDisplay(window).pack(expand='yes', fill='x')
I recommend to read up on how tkinter geometry managers work, e.g. here: http://effbot.org/zone/tkinter-geometry.htm
Note: it is not recommended (and leads to bugs) to mix different geometry managers. But it works if you use pack on the window level while using grid inside your frame - as you do to place the label with the grid method - just in case you want to add more widgets later inside your frame...
I have spent an embarassing amount of hours looking for a way to do this... Its for a project I'm working on that has over one hundred canvas items that need to update from a text file. Here is a simple version of that:
I would like to update a rectangle drawn in a canvas item when I push a button. I found a real bad hack way to do it that involves a crazy amount of code but I know there has to be some better way.
from tkinter import *
class MyGUI:
def __init__(self, root):
frame = Frame(root)
frame.pack()
self.BoxFillPercent = 0 # the canvas items get their % fill from this value
self.changeButton = Button(frame, text='SB', command=self.changeRange)
self.changeButton.grid(row=1, column=1)
self.hAA = Canvas(frame, width=35, height=35, bg='light blue')
self.hAA.grid(row=2, column=2)
self.hAA.create_rectangle(0,0,self.BoxFillPercent*35,35, fill="pink")
self.hAA.create_text(15, 15, anchor='center', text='AA')
def changeRange(self):
self.BoxFillPercent = 0.5
# When I push the button change the fill amount to 0.5
? What do I need to add here to make this work ?
root = Tk()
b = MyGUI(root)
root.mainloop()
I have tried to use update and update_idletasks among a bunch of other things but I must be missing something.
Every item on a canvas has an id. You can use the itemconfig method of the canvas to change the item.
rect = self.hAA.create_rectangle(...)
...
self.hAA.itemconfig(rect, ...)
If you need to apply the same change to multiple objects, you can give those objects a common tag and then use the tag in place of the id:
rect1 = self.hAA.create_rectangle(..., tags=("special",))
rect2 = self.hAA.create_rectangle(..., tags=("special",))
...
self.hAA.itemconfigure("special", ...)
I'm trying to have it so that multiple objects on a canvas in Tkinter can be resized/repositioned using a spinbox, with the value in the spinbox being used as a multiplier to the original coordinates. To make matters slightly more complicated, the spinbox is not visible by default, it's in a Toplevel window that can be opened when a button is pressed.
To summarise:
I need to alter the coordinates of objects on a canvas using a spinbox value as a multiplier (or otherwise) which itself is in a Toplevel window, and have these alterations displayed in 'real time' on the canvas.
For context, I've included the key peripheral code responsible for setting up the objects etc.
Essential Parts of UI module:
import Canvas_1 (module for drawing shapes)
root=Tk()
#root geometry, title set up
#UI then commands set up
canvasBlank=Canvas(root, width... etc) #Blank canvas that is drawn at start
canvasBlank.grid(row... etc)
canvasBlank.bind('Button-3', rightclickcanvas) #Right click function that opens a popup for canvas options
#Other misc commands, I'm using a menubar with drop down options over actual Tk.Buttons
#'New' option in menubar has Command to create objects in UI like:
def createObject():
Objects=MyObjects(root, width... etc)
Objects.grid(row... etc) #Same as layout for canvasBlank
Objects.bind('<Button-3>', rightclickcanvas)
Objectslist.append(Objects) #Stop garbage disposal and makes sure the canvas displays
-The MyObjects Class (in seperate module) has a form similar to:
from Coordinate_Generator import * #imports coordinate arrays
class MyObjects(tk.Canvas)
def __init__(self, master, **kw)
tk.Canvas.__init__(self, master, **kw)
self.create_oval(coordinates[0], dimensions[0], fill... etc)
self.create_oval(coordinates[1], dimensions[1], fill... etc)
#A series of bindings relating to moving objects under mouse clicks
The coordinates are determined using 'a', an arbitrary value. I try to multiply:
scaler=[]
a=70*scaler[-1]
This method doesn't seem to work either, and if it did, it also means potentially drawing a very large number of canvases over one another which I would like to avoid. I'm hoping this demonstrates the method I need to try and use more clearly. I have written a bit of code using the advice given, and while it may be useful for another part of the program I'm planning, it doesn't quite achieve what I am after. So I've cobbled together this 'Demonstration'to maybe illustrate what it is I'm trying to do.
Working Code (SOLUTION)
from Tkinter import *
from numpy import *
import Tkinter as tk
scale=1
class Demonstrator:
def __init__(self, master=None):
global full_coordinates, dimensions, scale
self.master=master
self.master.title( "Demonstrator 2")
self.master.grid()
self.master.rowconfigure(0, weight=1)
self.master.columnconfigure(0, weight=1)
self.canvas = Canvas(self.master, width=300, height=300, bg='grey')
self.canvas.grid(row=0, rowspan=3, column=0)
self.canvas.create_rectangle(full_coordinates[0],dimensions[0], activefill='blue', fill='red')
self.canvas.create_rectangle(full_coordinates[1],dimensions[1], activefill='blue', fill='red')
self.canvas.create_line(full_coordinates[0],full_coordinates[1], fill='red')
a=9*scale
Originx=10
Originy=35
coordinates1=[]
coordinates2=[]
x,y,i=Originx,Originy,1
x1,y1,i=Originx,Originy,1
while len(coordinates1)<=25:
coordinates1.append((x,y))
coordinates2.append((x1,y1))
i+=1
if i % 2 == 0:
x,y=x+a,y
x1,y1=x1,y1+a
else:
x,y=x,y+a
x1,y1=x1+a,y1
full_coordinates=list(set(coordinates1+coordinates2))
b=array(full_coordinates)
k=b+10
dimensions=k.tolist()
class Settings:
def __init__(self, parent):
top = self.top = tk.Toplevel(parent)
self.top.title('Settings')
self.spinbox_Label= tk.Label(top, text='Change Scale Factor?')
self.spinbox_Label.grid(row=0, column=0, columnspan=2)
self.spinbox_Label= tk.Label(top, width=30, text='Scale factor:')
self.spinbox_Label.grid(row=1, column=0)
self.spinbox= tk.Spinbox(top, from_=1, to=10, increment=0.1, command=self.change)
self.spinbox.grid(row=1, column=1)
def change(self):
global scale
scale=float(self.spinbox.get())
MG=Demonstrator(root) #This just generates a new Demonstrator with original coordinates
def onClick():
inputDialog = Settings(root)
root.wait_window(inputDialog.top)
def onClick2():
print scale
class coords:
global full_coordinates, dimensions, scale
print scale
a=9*scale
Originx=10
Originy=35
coordinates1=[]
coordinates2=[]
x,y,i=Originx,Originy,1
x1,y1,i=Originx,Originy,1
while len(coordinates1)<=25:
coordinates1.append((x,y))
coordinates2.append((x1,y1))
i+=1
if i % 2 == 0:
x,y=x+a,y
x1,y1=x1,y1+a
else:
x,y=x,y+a
x1,y1=x1+a,y1
full_coordinates=list(set(coordinates1+coordinates2))
b=array(full_coordinates)
k=b+10
dimensions=k.tolist()
root=Tk()
root.minsize=(700,700)
root.geometry=('600x600')
MG=Demonstrator(root)
mainButton2 = tk.Button(root, width=20, text='Print "scale"', command=onClick2)
mainButton2.grid(row=1, column=1)
mainButton = tk.Button(root, width=20, text='Settings', command=onClick)
mainButton.grid(row=2, column=1)
root.mainloop()
mainButton2.grid(row=1, column=1)
mainButton = tk.Button(root, width=20, text='Settings', command=onClick)
mainButton.grid(row=2, column=1)
root.mainloop()
The Question:
What is the best way to go about changing the size (by altering the coordinates) of the objects on the canvas using a spinbox?
I hope this is enough to info, of course I can supply more if necessary. I also apologise in advance for the formatting of this question, I'm new to this :)
(Solution added)
Any help would be awesome. Cheers.
Mark
There's nothing special about the solution. You simply need to define a callback for the spinbox that adjusts the coordinates of the canvas items (which can be done with the coords method of the canvas).
First, you might want to create a dict to contain the base width and height of each item. The keys to this dictionary could also be tags associated with canvas items. For example:
self.base_dimensions = {
"obj1": (10,10),
"obj2": (20,20),
...
}
Next, create items on a canvas using those keys as tags. For example:
...
self.canvas.create_rectangle(..., tags=("obj1",))
self.canvas.create_rectangle(..., tags=("obj2",))
...
Finally, you can save the spinbox widgets in a dictionary using the same keys (so you can associate a spinbox with a canvas object), and assign the spinbox a callback to do the resizing. For example:
self.spinbox = {
"obj1": tk.Spinbox(..., command=lambda self.do_resize("obj1")),
"obj2": tk.Spinbox(..., command=lambda self.do_resize("obj2")),
...
}
Given a tag, your callback can use that to get the reference to the spinbox widget and get it's value, and then use the tag to tell the canvas object which item(s) to resize. For example:
def do_scale(self, tag):
factor = int(self.spinbox[tag].get())
(width, height) = self.default[tag]
(x0,y0,x1,y1) = self.canvas.coords(tag)
width = factor * width
height = factor * height
x1 = x0 + width
y1 = y0 + height
self.canvas.coords(tag, x0,y0,x1,y1)
Of course, there are endless ways to organize your data; what I've shown isn't the best way nor the only way. It might not even work for how you have your code organized. Whatever you choose, it boils down to being able to get the value out of the spinbox and using it to adjust the coordinates of the canvas items.
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')
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()
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()
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.
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.
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()
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.
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()
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.