This question already has answers here:
Tkinter Frame container color not visible
(2 answers)
Closed 4 years ago.
I feel like I am missing something very basic here. This is my first try creating a GUI in Python. I try to add several frames inside my main window and place stuff inside by using grid manager. The frame creation and sizing and stuff works fine, until I add anything inside the frame. Like in this example with only one frame, when I put my dummy label, the frame just completely vanishes and only the label is displayed.
I really want to understand what is going on and why it is behaving like it is ... and of course, how to fix it. Thanks a lot.
from tkinter import *
window = Tk()
# Window geometry
window.title("Tk")
window.geometry('850x600')
# Set Frames
LeftTopFrame = Frame(window,bg='red',height=200,width=300)
LeftTopFrame.pack(fill=X,side=LEFT)
lblInp = Label(LeftTopFrame, text='Label',font=('Tahoma', 10))
lblInp.grid(column=0,row=0)
window.mainloop()
Tkinter frames shrink or grow to fit their contents. Use
LeftTopFrame.grid_propagate(0)
Related
This question already has an answer here:
When should I use root.update() in tkInter for python
(1 answer)
Closed 1 year ago.
Beginner programmer here currently trying to learn Tkinter for a school assignment.
I have a GUI class that stores the Tkinter labels etc, the labels are innitiated like this:
# GUI for Player 1
self.player_1_name_field = Label(
self.root,
text="Player 1",
font=GUI_Settings.player_information_font,
anchor=W,
background=GUI_Settings.playerfield_active_color
)
I then create a Game() object that looks like this:
class Game():
def __init__(self):
self.GUI = GUI()
self.GUI.initializeBoard()
self.GUI.root.mainloop()
When I run the code, the labels do get created and are where they are supposed to be, but are completely black. Once I move or resize the window it instantly becomes how I want it to be, it just behaves weird when at the start of the code
The interesting thing is that I also have a Canvas and a List that work perfectly fine, only the Labels are not cooperative
If you need further info, just ask for it!
Thank you!
Edit 1: I have a function called drawWindow() that redraws the chessboard when I re-configure the window. In the init of the GUI class I set self.root.bind("<Configure>", self.drawWindow). If I remove that line of code, the Labels work but the Canvas doesn't anymore. I'm so confused. For anyone wanting to take a look at my tiny code: https://codeshare.io/DZYzyZ
See comment of Thingamabobs
The issue is self.root.update(). Remove this line and you'll be fine.
When should I use root.update() in tkInter for python.
This works but you shouldn't do it
This is a tricky issue. Your problem come from the bind of the configure event. Bind to the root window, it is applied to all sub-widgets of the window, which cause the bug (I don't know why yet).
This will solve your issue (line 202):
self.chessboard.bind("<Configure>", self.drawWindow)
instead of:
self.root.bind("<Configure>", self.drawWindow)
Result without moving or resizing the window:
I found the information here (french forum).
This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 2 years ago.
this code is just an example
code:
import tkinter as tk
root = tk.Tk()
photoImageObj = tk.PhotoImage(file="signout.png")
lab = tk.Label(root, image=photoImageObj).pack()
photoImageObjj = tk.PhotoImage(file="signout.png")
signout_button=tk.Button(root,image=photoImageObjj).pack()
root.mainloop()
In this code it is working and output is also working fine.
here is the output:
but in my real project, where I am using this button with the image is not working.
code:
photoImageObj = PhotoImage(file="signout.png")
signout_button=Button(stem,image=photoImageObj).pack()
here I haven't pasted my whole code since it is having 50-60 line's of code.
Output:
so if the same code is working fine, then there is problem in my real project file.
so can anyone help me debug that.
When an image is inside a function you have to keep reference to the image or it will be garbage collected by python. With the code provided its hard to say, but just try something like:
signout_button = Button(stem,image=photoImageObj)
signout_button.pack() #so that signout_button is not None
signout_button.image=photoImageObj #keeping a reference
Alternatively, you could also say global photoImageObj on top of function, but its not recommended to use global. This question should be marked as a duplicate and closed, but just in-case you dont understand what to do in your "specific case", here is the answer.
I am a newbie to python and Tkinter, please mind my silly mistakes if any.
The code I am attaching is a generalised and simpler version in order to get and test simply. Once I am ok with it, will prepare the application code.
I have two frames, who have their parent as the root geometry window.
Each frame has many canvases drawn in my main application, but I am drawing only one sample rectangle in my question for the sake of making it short.
My problem is while I draw two canvas on two different frames, on running the program, both appear simultaneously.
import tkinter as tk
from tkinter import ttk
from tkinter import font
from tkinter import *
root=tk.Tk()
root.geometry("550x550")
Crel='groove'
Cbw=3
h=50
w=50
#####Frame 1 & rectangle Canvas drawn########
Cparent=ttk.Frame(root,height=200,width=200)
Cparent.pack()
hallname=tk.Canvas(Cparent,height=h,width=w,relief=str(Crel),
borderwidth=int(Cbw))
hallname.place(x=150,y=150)
#####Frame 2 & rectangle Canvas drawn########
Cparent2=ttk.Frame(root,height=200,width=200)
Cparent2.pack()
hallname1=tk.Canvas(Cparent2,height=h,width=w,relief=str(Crel),
borderwidth=int(Cbw))
hallname1.place(x=30,y=30)
#####Function to switch frames########
def pushbut(obj):
obj.tkraise(obj)
#####Buttons size and font#######
buttonnamefont=font.Font(root,family="Helvetica",size=10,weight="bold")
Details=Button(root,text='Details',font=buttonnamefont,
command=lambda:pushbut(Cparent))
Overview=Button(root,text='Overview',font=buttonnamefont,
command=lambda:pushbut(Cparent2))
Overview.place(x=300,y=520)
Details.place(x=100,y=520)
Cparent.tkraise()
root.update()
If i try to show one frame using tkraise function, still the other frame also shows up.
About switching frames, I have made two buttons,and tried to switch between frames using lamba function, however failed to do so.
Please let me know for minute and idiotic mistakes if made by me;)
I am running into a problem with a tkinter program, I have the LabelFrame grouping a set of labels and entries, however, it is not grouping my widgets. My code for the LabelFrame is as follows:
(edit: i managed to get the Label to display, however, it is not grouping my widgets.)
root=Tk()
message_frame=LabelFrame(root,text="testing",padx=0,pady=0,width=100,height=100).grid(padx=5,pady=10)
message_label=Label(message_frame,text="Message").grid(row=1,column=0,sticky=W)
pub_label=Label(message_frame,text="Public Key").grid(row=2,column=0,sticky=W)
priv_label=Label(message_frame,text="Public Key").grid(row=3,column=0,sticky=W)
message_entry=Entry(message_frame,textvariable=message,width=50).grid(row=1,column=1,sticky=W)
pub_entry=Entry(message_frame,textvariable=pub_key,width=50).grid(row=2,column=1,sticky=W)
priv_entry=Entry(message_frame,textvariable=private_key,width=50).grid(row=3,column=1,sticky=W)
In Tkinter, the typical workflow is to create a widget and then place it using some geometry manager on two separate lines.
If I'm not mistaken, the .grid method on Tkinter widgets returns None. So if you print message_frame right after you create it, you will probably see that it is None. When you use that passed to the next widgets, they assume you want to put it on the root widget...
The easy fix is to do something like:
message_frame=LabelFrame(root,text="testing",padx=0,pady=0,width=100,height=100)
message_frame.grid(row=0,column=0)
And you probably want to do the same with all the widgets since I doubt you actually want pub_label = priv_label = None ...
Give the frame some size attributes:
from Tkinter import *
root = Tk()
message_frame = LabelFrame(root,text="testing",padx=0,pady=0,width=100,height=100).grid(row=0,column=0,padx=5,pady=10)
Once the width and height are defined, the frame shows up fine.
If you post some of your frame's contents, it might make it clearer if this is not the issue.
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)