tkinter - LabelFrame not displaying label - python

I am trying to create a LabelFrame in tkinter, however the "title" of the frame is not displayed, neither is the border around the LabelFrame.
Minimal example:
import tkinter as tk
root = tk.Tk()
root.title("Test")
root.geometry("400x400")
instance = tk.Label(root, text="SCTL:").pack()
labelframe = tk.LabelFrame(root, text="Title of Frame").pack()
instance2 = tk.Label(labelframe, text="some text").pack(padx=10, pady=10)
root.mainloop()
This example will get "some text" displayed, however "Title of Frame" will not.
I am using Python 3.8.8 and tkinter 8.6.10. Does anybody have an idea how I can get the title of the frame and its border to be displayed?
Thank you in advance!

So the problem here is that you are initializing and packing the labelframe in the same line as #jasonharper pointed out -: labelframe = tk.LabelFrame(root, text="Title of Frame").pack().
Note that this does not work, since the variable labelframe does not get assigned the newly initialized labelframe object but rather the return value of the called function pack.
This means that if we write the same in two different lines, one for object initialization and the other for packing, the problem disappears. Like so -:
labelframe = tk.LabelFrame(root, text="Title of Frame") # First initialize the object and store it in the variable.
labelframe.pack() # Then use the variable to pack it.
In general also if a tkinter widget is to be used for long term in a program I suggest not packing it in the same line as it's initialization, this not only looses the newly initialized object's reference but also can cause such problems.
But the same if is temporary then can be done in one line. Here you were using the LabelFrame in the next line and thus should have separately done the packing and the initialization.

Related

tkinter, pack inside grid and propagation not working

I am trying to create a button with a fixed size. So, I created a Frame (grid) with the size I want and then a child Button (pack) inside of the Frame that takes all the space.
Here is a minimal example:
window = tk.Tk()
frame1 = tk.Frame(window, bg="#ffffff", height=50, width=100)
frame1.grid(row=0, column=0)
frame1.grid_propagate(0)
#frame1.propagate(False) # <----- This line makes it work.
button1 = tk.Button(frame1, bg="#000000")
button1.pack(expand=True, fill=tk.BOTH)
Without the commented line above, I expected that it would work (having a rectangle of the specified size), but I get a small square. Why is it not working?
I was not able to find documentation on that .propagate() function. I only found about the grid_propagate() and pack_propagate() functions.
Right now you have 2 containers: window and frame1. When you use frame1.grid(...), you actually tell the master of frame1, which is window that it should use the grid manager. When you use button1.pack(...), you tell the button's master (frame1) that it should use the pack manager inside itself.
So when you use frame1.grid_propagate(...), you tell the grid manager (that doesn't manage the widgets inside frame1), that it should do something, so it ignores you.

Entanglement between Tkinter Checkbuttons

Hey so i'm making a program that has a checkbutton on the main window and a toplevel window that has one aswell. the problem is that for some reason the toplevel checkbutton affects the state of the main checkbutton, or the main checkbutton mimics the top level one (if you check/uncheck the toplevel one, the main one checks/unchecks aswell). Here's an example code which displays the problem:
import tkinter as tk
def toplevel():
top = tk.Toplevel()
top.geometry('200x50')
top_chekbutton = tk.Checkbutton(top, text='top')
top_chekbutton.pack()
top.mainloop()
main = tk.Tk()
main.geometry('200x50')
open_top = tk.Button(main, text='open top', command=toplevel)
main_checkbutton = tk.Checkbutton(main, text='main')
main_checkbutton.pack()
open_top.pack()
main.mainloop()
i didn't define the state variables because they don't seem to be the source of the problem. i'm using python 3.7.7 and tkinter 8.6 on win10.
plz help :(
As a general rule of thumb, every instance of Checkbutton should have a variable associated with it. If you don't, a default value will be used that is identical for all Checkbuttons. All widgets that share the same variable will display the same value.
You can verify this yourself by printing out the value of top_chekbutton.cget("variable") and main_checkbutton.cget("variable"). In both cases the value is "!checkbutton" (at least, with the version of python I'm using).
So, assign a variable for your checkbuttons, such as a BooleanVar, IntVar, or StringVar.
main_var = tk.BooleanVar(value=False)
main_checkbutton = tk.Checkbutton(main, text='main')

I get more than one master from widget.master (Python 3)

I just wrote a class in Tkinter, that allows me to make some widgets draggable. This really works great as long as the master of the widget is the root window. But if I, for example, have a Frame with a Lable in it, I can drag the Frame but the Lable just disappears. This is cause the class places the label in relation to the main window. So for example, if the Frame has the size 100x100 and is at the position 500, 500 at the main window, and I drag the Label(0, 0) 1px to the right, it will be placed at 501, 500 instead of 1, 0 cause the class thinks the master is the root window.
So now I thought to just use the master's position to subtract it from the Label position (501-500, 500-500 > 1, 0) There's just one problem. This:
f = Frame(root, width=100, height=100, bg='grey')
f.place(x=500, y=500)
l = Label(f, text='Drag me!)
l.place(x=0, y=0)
master = l.master
print(master)
returns me not one master but two. Even if there's just one print statement, it gives me this:
>>.
>>.!frame
If I put a sleep statement in between the declaration and the print it just takes longer. But if I check the types it's not a list, this are two objects.
Can anybody explain this? I just need a way to get the master of the Label to get it's position!
Tkinter widgets exist in a tree structure, and there must be an instance of Tk at the root. If you don't create one, it will be created for you the first time you create a widget.
In your output, "." represents the root window that was presumably created for you, and ".!frame" represents the frame.
Though, given the fact that you explicitly pass root to Frame(), it looks like your code is explicitly creating the root window somewhere.
I found the problem. It's not a problem with the code. I just didn't noticed I also müde the Frame dragable. And cause the Frames parent is root I got it.

tkinter's .pack_propagate() method

I am experimenting with Tkinter, as I was trying to figure out is there a way to set the tkinter's window size without using canvas. I came upon this how to set frame size question on SO's Question & Answer. So I went ahead and test it by writing a very small program to display a text label. But I found out it is "missing", or disappear when I use frame.pack_propagate(0)
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, width=400, height=400)
# Does not work at the moment, textBox is missing
# frame.pack_propagate(0)
frame.pack()
textBox = tk.Label(frame, text="(x,y): ")
textBox.pack()
root.mainloop()
So my question is, can you explain why my textBox (Label) is not appearing when I use the frame.pack_propagate(0) instead of frame.pack() method? And secondly, is there a way to set the window size without using a canvas? I want to know because I am writing a series of small programs to teach my friend about tkinter, before introducing canvas to him. It would be nice if the window size are all the same across my tkinter samples. And I am just wondering as well (curious). Thank you very much.
I am using python 3.2.2 on MAC OS 10.5.8.
pack_propagate only sets a flag, it doesn't cause the frame to be placed in the widget. It is not a substitute for calling pack.
In other words you must do this:
# put the frame in its parent
frame.pack()
# tell frame not to let its children control its size
frame.pack_propagate(0)
# put the textbox in the frame
textBox.pack()
To answer your second question: Yeah, there is a way.
tkinters Tk do have the Tk.geometry function. When you just call it without arguments, you will get the current geometry in form of 'widthxheight+x+y', so for example (on Windows 10) '200x200+26+26' when you create your first Tk window. Using that format you can resize the Tk by, e.g., writing: root.geometry('400x500+60+60') to set the width to 400, the height to 500 and place it at the coordinates (60|60).
This works for Tk alswell as for Toplevel. But Toplevel also takes the arguments height and width when initialized or configured. If you want them to keep their size when packing something inside just use root.pack_propagate(False) on them.
By the way there is something similar for the grid manager: root.grid_propagate(False)

Python Tkinter - change the canvas size after inital declaration

I want to change the canvas size after I have added some widgets to it
Example:
from Tkinter import *
master = Tk()
w = Canvas(master, width=100, height=100)
w.config(bg='white')
w.create_oval(90,90,110,110, width=0, fill = "ivory3")
w = Canvas(master, width=200, height=200)
w.pack()
mainloop()
But it seem that when I re-declare the canvas size, the objects get removed.
Is it possible to update the canvas after I have created some objects on it?
What you are looking for is the configure option, as is documentered here. Basically, something like this should help, in place of creating a new canvas:
w.config(width=200, height=200)
For reference, the reason why everything got deleted off of the Canvas is because you created a brand new Canvas, with a different size and the same name. If you are going to change properties of an existing object, you must change the existing object, and not overwrite it. Basically you overwrite something if you declare it equal to something else (w=Canvas(...)).
You can easily resize to canvas with the .config() command like so:
w.config(width=x height=y)
The x and y represent integers (whole numbers). You can also add on some other customisation attributes like bg (background) to further customise the canvas.
Also, you have created a brand new canvas at the end there so that is why your attributes disappeared. You can fix that by deleting the last 2 lines of code starting with w =.

Categories

Resources