How do I make a LabelFrame's frame not visible? (Tkinter) - python

My code is the following:
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('None')
label = ttk.LabelFrame(window, text = 'What I want to delete')
label.grid(column = 0, row = 0, padx = 5, pady = 5)
text = ttk.Label(label, text = 'Hello World')
text.grid(column = 0, row = 0)
window.mainloop()
with frame
Now what surprises me is that when I do the following changes:
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('None')
label = ttk.LabelFrame(window, text = 'What I want to delete').grid(column = 0, row = 0, padx = 5, pady=5)
text = ttk.Label(label, text = 'Hello World').grid(column = 0, row = 0)
window.mainloop()
The label's frame does not appear. Only the text. As shown below:
without frame
Which means that the LabelFrame is existent, but not shown because there's no error. I think.
In summary, that's the way I "solved it". So, my question is, Is there a fuction that makes It possible not to show the frame in a LabelFrame?

ttk.LabelFrames are only visible if there is something inside it or if they have a fixed size. In the fisrt example you gave the ttl.Label widget with text='Hello Word' is clearly inside the LabelFrame since you passed it as its parent. But in the second example it's not. You may think it is because you also defined label as the ttk.Label parent but if you do print(label) you will see it will print None and, in tkinter, if you pass None as a widget master it will understand that the master is the root Tk() widget.
So, why this happens? The difference between the two examples is that in the first label=ttk.LabelFrame() which is a LabelFrame object (an instance of the LabelFrame class), while in the second label=ttk.LabelFrame().grid() which is the output of the grid method, and since the grid method does not return anything label is equal to None. In conclusion what you are doing is putting the LabelFrame with anything inside and then the second Label, both in the same position of the master window and this is why you can't see the LabelFrame.
Ok, then how to make the LabelFrame invisible? The best option is not using ttk.LabelFrame but tk.LabelFrame because now you can disappear with the border using label.configure({"relief":"flat", "text":""}). Of course this will look like the frame is not there, but everything inside the frame will still be visible. If you want to disappear with things inside the label you can use either label.destroy() (you will not be able to recover the label) or label.grid_forget() (which will only 'ungrid' the label).

Related

How can I place a widget at the very bottom of a tkinter window when positioning with .grid()?

I am aware that you cannot use different types of geometry managers within the same Tkinter window, such as .grid() and .pack(). I have a window that has been laid out using .grid() and I am now trying to add a status bar that would be snapped to the bottom of the window. The only method I have found online for this is to use .pack(side = BOTTOM), which will not work since the rest of the window uses .grid().
Is there a way that I can select the bottom of the window to place widgets from when using .grid()?
from tkinter import *
from tkinter.ttk import *
import tkinter as tk
class sample(Frame):
def __init__(self,master=None):
Frame.__init__(self, master)
self.status = StringVar()
self.status.set("Initializing")
statusbar = Label(root,textvariable = self.status,relief = SUNKEN, anchor = W)
statusbar.pack(side = BOTTOM, fill = X)
self.parent1 = Frame()
self.parent1.pack(side = TOP)
self.createwidgets()
def createwidgets(self):
Label(self.parent1,text = "Grid 1,1").grid(row = 1, column = 1)
Label(self.parent1,text = "Grid 1,2").grid(row = 1, column = 2)
Label(self.parent1,text = "Grid 2,1").grid(row = 2, column = 1)
Label(self.parent1,text = "Grid 2,2").grid(row = 2, column = 2)
if __name__ == '__main__':
root = Tk()
app = sample(master=root)
app.mainloop()
So using labels since I was kinda lazy to do other stuff, you can do frames to ensure that each section of your window can be packed/grid as required. Frames will be a useful tool for you to use when trying to arrange your widgets. Note that using a class can make things a little easier when deciding your parents. So imagine each frame is a parent and their children can be packed as required. So I would recommend drawing out your desired GUI and see how you will arrange them. Also if you want to add another frame within a frame simply do:
self.level2 = Frame(self.parent1)
You can check out additional settings in the docs
http://effbot.org/tkinterbook/frame.htm
PS: I am using a class hence the self, if you don't want to use classes then its okay to just change it to be without a class. Classes make it nicer to read though
Just give it a row argument that is larger than any other row. Then, give a weight to at least one of the rows before it.
Even better is to use frames to organize your code. Pack the scrollbar on the bottom and a frame above it. Then, use grid for everything inside the frame.
Example:
# layout of the root window
main = tk.Frame(root)
statusbar = tk.Label(root, text="this is the statusbar", anchor="w")
statusbar.pack(side="bottom", fill="x")
main.pack(side="top", fill="both", expand=True)
# layout of the main window
for row in range(1, 10):
label = tk.Label(main, text=f"R{row}")
label.grid(row=row, sticky="nsew")
main.grid_rowconfigure(row, weight=1)
...

tkinter grid manager behaviour

So i want to build an assistant off sorts which will do auto backs ups etc and instead of using .place i would like a proper grid to place widgets.
I cannot find a good example of the grid manager.
self.parent = tk.Frame(window, bg = BLACK)
username_label = ttk.Label(self.parent, text = "Username")
password_label = ttk.Label(self.parent, text = "Password")
self.parent.grid(column = 0, row = 0)
username_label.grid(column = 1, row = 1)
password_label.grid(column = 2, row = 2)
self.parent.grid_columnconfigure(0, weight = 1)
I want...
Button
Button
Label Entry Button
Label Entry Button
Button
I don't understand how i can position them like this as i want a blank space above the labels. so far grid has only let me place things next to each other.
Honestly, any websites or code examples would be greatly appreciated
So, if you want blank space above the label, you can either set pady as an argument to the grid method or simply put them in the corresponding row. Consider the following example:
import tkinter as tk
root=tk.Tk()
for i in range(6):
tk.Button(root,text='Button %d'%i).grid(row=i,column=1)
tk.Label(root,text='Label 0').grid(row=2,column=0,pady=20)
tk.Label(root,text='Label 1').grid(row=3,column=0)
root.mainloop()
Notice the effect of the pady argument. Also, if you only want a blank line above the Label, you can try to put a blank Label in the row above. E.g.:
import tkinter as tk
root=tk.Tk()
for i in range(6):
tk.Button(root,text='Button %d'%i).grid(row=i,column=1)
tk.Label(root,text='Label 0').grid(row=2,column=0,pady=20)
tk.Label(root,text='Label 1').grid(row=3,column=0)
tk.Label(root,text='').grid(row=6)
tk.Label(root,text='This is a Label with a blank row above').grid(row=7,columnspan=2)
root.mainloop()
You can refer to effbot for more information, which is the blog of tkinter's developer.

Python Tkinter Label not updating in new window

So I've got a function that opens a new window. In this window I am trying to update a Label, when I use textvariable it doesn't update and the label always stays blank. With just text, the label will show the text.
My textvariable's work in my main window but not in this one and I have no idea why.
def Manage():
PropsP1 = Tk()
area = Canvas(PropsP1, width = 920, height = 970)
area.pack()
MedCR = StringVar()
MedO = 1
count = 1
MedR = 4
if MedO == count:
MedCRLabel = Label(PropsP1, textvariable=MedCR, bg = "White")
MedCRLabel.place(x = 15, y = 65)
MedCR.set("Current Rent: "+str(MedR))
This is the function, I've tried making multiple Labels and none display anything with textvariable. I can see a white square for the label so I know it is showing up but there is no text.
The problem is that you are creating a new instance of Tk. A tkinter application should only ever create a single instance of Tk, and call mainloop exactly once. To create a popup window, create an instance of Toplevel.

Python Scrollbars on text widget in grid layout

So I have a text widget with multiple lines populated. I have the following code that creates the text widget, scrollbar and assigns them to each other. However, right now the text box has disappeared and the scroll bar is scrunched up real small. What's wrong?
txt_domains = Text(root,height=10,width=20)
txt_domains.grid(row=1,column=1)
scr_domains = Scrollbar(txt_domains,orient='vertical')
scr_domains.grid(row=1,column=2)
txt_domains.config(yscrollcommand=scr_domains.set)
scr_domains.config(command=txt_domains.yview)
UPDATE:
Using the following modification:
txt_domains = Text(root,height=10,width=20)
txt_domains.grid(row=1,column=1)
scr_domains = Scrollbar(root,orient='vertical')
scr_domains.grid(row=1,column=2,sticky='sn')
txt_domains.config(yscrollcommand=scr_domains.set)
scr_domains.config(command=txt_domains.yview)
I know get this result:
For some reason everything shifted over? SOLUTION: Change the txt_domains to column=0 and scrollbar to column=1.
I think the problem is that the parent of your scrollbar is txt_domains instead of frame or root window (depend on your code). This should work well:
from tkinter import *
root = Tk()
txt_domains = Text(root,height=10,width=20)
txt_domains.grid(row=1,column=1)
scr_domains = Scrollbar(root,orient='vertical')
scr_domains.grid(row=1,column=2, sticky=S+N)
txt_domains.config(yscrollcommand=scr_domains.set)
scr_domains.config(command=txt_domains.yview)
root.mainloop()

Python - TKinter - Destroying widgets not lowering frame height

I am having and issue where I have a frame in a game that displays the current progress of the game (let's call this frame; "results").
If the player chooses to start a new game all the widgets inside results get destroyed and the frame is forgotten to hide it until it is used again.
Now the issue I am having is; When results gets called back it is in-between two other frames. However, it has remained the size it was in the previous game when it has contained all the widgets, before the widgets were destroyed. The widgets are not shown in the frame but it's still the size it was when the widgets were there.
As soon as a new widget is placed in results the size is corrected but I can't figure out how to make the height = 0. I have tried results.config(height=0) but that hasn't worked.
Does anyone know how to "reset" the size of the frame to 0?
Sorry for the proverbial "wall-of-text" but I couldn't find a way to provide the code in a compact way.
Thanks
If I completely understand what you want, then this illustration is correct:
The blue is the results frame
The results removed, everything else resized:
And the corresponding code for this is something like:
import tkinter
RESULTS_WIDTH = 128
root = tkinter.Tk()
left_frame = tkinter.Frame(root, height=64, bg='#cc3399')
right_frame = tkinter.Frame(root, height=64, bg='#99cc33')
def rem_results(event):
# Remove widget
results.destroy()
# Resize other widthets
left_frame.config(width=128 + RESULTS_WIDTH/2)
right_frame.config(width=128 + RESULTS_WIDTH/2)
# Reposition other widgets
left_frame.grid(row=0, column=0)
right_frame.grid(row=0, column=1)
def add_results(event):
# Create results widget
global results
results = tkinter.Frame(root, width=RESULTS_WIDTH, height=64, bg='#3399cc')
results.grid(row=0, column=1)
# Resize other widgets
left_frame.config(width=128)
right_frame.config(width=128)
# Reposition other widgets
left_frame.grid(row=0, column=0)
right_frame.grid(row=0, column=2)
# Initialize results
add_results(None)
# Bind actions to <- and -> buttons
root.bind( '<Left>', rem_results )
root.bind( '<Right>', add_results )
#$ Enter eventloop
root.mainloop()

Categories

Resources