= 2.2 A small lexicon of widgets - Part 2
== Non-clickable widgets
The next four widgets fall into the **non-clickable** category. They’re designed to present **textual** information and don’t have a ''command'' property, although you can use ''bind()'' to simulate similar behavior.
The ''Label'' widget displays some lines of text inside the window:
label = Label(master, option, ...)
The ''Label'' widget contains two usable properties, but you need to remember that they are mutually exclusive.
Here you are:
{{:info:cursos:pue:python-pcpp1:m3:pasted:20231228-111139.png}}
The Label widget has no usable methods – sorry!
The sample in the editor shows how the ''textvariable'' accompanied by an observable variable can be used to **continuously** update the ''Label''’s contents.
import tkinter as tk
def to_string(x):
return "Current counter\nvalue is:\n" + str(x)
def plus():
global counter
counter += 1
text.set(to_string(counter))
counter = 0
window = tk.Tk()
button = tk.Button(window, text="Go on!", command=plus)
button.pack()
text = tk.StringVar()
label = tk.Label(window, textvariable=text, height=4)
text.set(to_string(counter))
label.pack()
window.mainloop()
The ''Message'' widget is very similar to the ''Label'' (among other things, it has the **same properties**) but is able to **format** the presented text by fitting it automatically to the widget’s size.
message = Message(master, option, ...)
The sample code will tell you more.
import tkinter as tk
def do_it_again():
text.set(text.get() + "and again...")
window = tk.Tk()
button = tk.Button(window, text="Go ahead!", command=do_it_again)
button.pack()
text = tk.StringVar()
message = tk.Message(window, textvariable=text, width=400)
text.set("You did it again... ")
message.pack()
window.mainloop()
Run it and see how the ''Message'' widget reacts to the ''tx'' variable updates.
The ''Frame'' widget is, in fact, a ''container'' designed to store other widgets. This means that the ''Frame'' can be used to separate a **rectangular part** of the window and to treat it as a kind of //local window//. Such a //window works// as a **master widget** for all the widgets embedded within it. Moreover, the ''Frame'' has its **own** **coordinate system**, so when you place a widget inside a Frame, you measure its location relative to the Frame’s **upper-left corner**, not the window’s one. It also means that if you move the ''Frame'' to a new position, all its inner widgets will go with it.
Note: the ''Frame'' can grasp virtually any widget – including another ''Frame''.
The ''Frame'' has one interesting property:
{{:info:cursos:pue:python-pcpp1:m3:pasted:20231228-111827.png}}
Take a look at the example in the editor.
import tkinter as tk
window = tk.Tk()
frame_1 = tk.Frame(window, width=200, height=100, bg='white')
frame_2 = tk.Frame(window, width=200, height=100, bg='yellow')
button_1_1 = tk.Button(frame_1, text="Button #1 inside Frame #1")
button_1_2 = tk.Button(frame_1, text="Button #2 inside Frame #1")
button_2_1 = tk.Button(frame_2, text="Button #1 inside Frame #2")
button_2_2 = tk.Button(frame_2, text="Button #2 inside Frame #2")
button_1_1.place(x=10, y=10)
button_1_2.place(x=10, y=50)
button_2_1.grid(column=0, row=0)
button_2_2.grid(column=1, row=1)
frame_1.pack()
frame_2.pack()
window.mainloop()
We’ve defined two separate frames and filled them with two buttons each. Note: we’ve used different geometry managers for both ''Frames''. This is another advantage of the ''Frame'' – it helps you arrange the window in the most convenient way.
Pay attention to all four of the ''Buttons''’ constructors – how have we described a master widget there?
The ''LabelFrame'' widget is a ''Frame'' enriched with a **visible border** and a **title** (also visible). The title may be located at one of 12 possible places on the border line.
lfrm = LabelFrame(master, option, ...)
Some of the usable ''LabelFrame'' properties are gathered here:
{{:info:cursos:pue:python-pcpp1:m3:pasted:20231228-112139.png}}
We’ve rebuilt our previous example to employ a ''LabelFrame'' instead of a ''Label'' – look at the updated code we've provided in the editor.
import tkinter as tk
window = tk.Tk()
label_frame_1 = tk.LabelFrame(window, text="Frame #1",
width=200, height=100, bg='white')
label_frame_2 = tk.LabelFrame(window, text="Frame #2",
labelanchor='se', width=200, height=100, bg='yellow')
button_1_1 = tk.Button(label_frame_1, text="Button #1 inside Frame #1")
button_1_2 = tk.Button(label_frame_1, text="Button #2 inside Frame #1")
button_2_1 = tk.Button(label_frame_2, text="Button #1 inside Frame #2")
button_2_2 = tk.Button(label_frame_2, text="Button #2 inside Frame #2")
button_1_1.place(x=10, y=10)
button_1_2.place(x=10, y=50)
button_2_1.grid(column=0, row=0)
button_2_2.grid(column=1, row=1)
label_frame_1.pack()
label_frame_2.pack()
window.mainloop()
Run it and find the differences.