How do I align my Radiobuttons? I can add spaces to test4 but that solution doesn't seem proper. Here's what it looks like at the moment—as you can see text111111 has extra chars. I've tried using padx.
My code:
from tkinter import *
class GUI:
def __init__(self, master):
self.iconnum = IntVar()
self.master = master
self.master.title('test')
self.master.resizable(width=False, height=False)
self.master.maxsize(500, 250)
self.master.minsize(500, 250)
self.test1 = Radiobutton(master, text="test11111111", variable=self.iconnum,
value=1, )
self.test2 = Radiobutton(master, text="test2", variable=0, value=2, )
self.test3 = Radiobutton(master, text="test3", variable=0, value=3, )
self.test4 = Radiobutton(master, text="test4", variable=0, value=4)
self.test1.grid(row=2, columnspan=1)
self.test2.grid(row=2, columnspan=2)
self.test3.grid(row=2, column=1)
self.test4.grid(row=3, columnspan=1)
self.Checker = Radiobutton(master, text="test5", indicatoron=0, height=1, width=35,
value=0, command=self.icon_switcher) #var=Selection)
self.Turbo = Radiobutton(master, text="test6", indicatoron=0, height=1, width=35,
value=1, command=self.icon_switcher) #var#=Selection)
self.Checker.grid(row=1)
self.Turbo.grid(row=1, column=1, )
def icon_switcher(self):
print("Hello")
root = Tk()
gui = GUI(root)
root.mainloop()
You should use the sticky keyword argument in order to align your widgets better when using grid.
import Tkinter as tk
window = tk.Tk()
radio = tk.Radiobutton(window, text="I'm a radio")
radio.grid(column=0, row=0, sticky=tk.N+tk.S+tk.W+tk.E)
window.mainloop()
You can use any combination of the N, S, W and E members of the Tkinter module. This parameter will make your widgets stick to the sides of the cell you have specified, somewhat like justification in text. If your widget is resizable, such as with Button, the widget will also automatically resize to fit the cell if you use all of the N, S, W and E members.
Important to note is that this can only do so much as to make the widgets stick to the edges of the cell. Sometimes it is necessary to actually resize the cell or move your widget to another cell.
In your example image, you have Buttons with a set size that is larger than the default size (the example code you provide is incomplete). This causes the cell, and the whole columns that the cells of these Buttons are in, to become wider. In this case, you might want to use the columnspan keyword argument to divide your column into smaller, resizable, parts, so that your Radiobuttons can be aligned still better.
import Tkinter as tk
window = tk.Tk()
radio_one = tk.Radiobutton(window, text="I'm a radio")
radio_two = tk.Radiobutton(window, text="I'm another radio")
button = tk.Button(window, text="I am a very long button", width=50)
button.grid(row=0, column=0, columnspan=2, sticky=tk.N+tk.S+tk.W+tk.E)
radio_one.grid(column=0, row=1, sticky=tk.N+tk.W)
radio_two.grid(column=1, row=1, sticky=tk.N+tk.W)
window.mainloop()
If you would like more information on what parameters the grid geometry manager can use, I suggest you read this tutorial, I have found it to be very helpful in the past.
As a sidenote, please note that you use the variable keyword argument in the declaration of your Radiobuttons incorrectly. You must pass either a tk.StringVar, tk.IntVar or some other comparable object, as described here.
You can use sticky=W inside your .grid for all your buttons to make them align on the left side. And you can also include pady = 20 to make it not go all the way to the left.
Related
Some background:
I have a class that inherits from tk.Label; basically, a Label widget that has some extra methods tuned to my taste.
I have two design modes for the label, and a function switching between them. Mode 1 is a simple look with black text; mode 2 is a look that has two empty blue frames inside the label, solely for design purposes (but are required).
The custom-widget (let's name it Cell) is bound to a function that changes the bg color (no matter which mode) of the Cell when clicked, and reverts when released.
Now, the situation:
Case I:- When Cell object is in "mode 1"
When the label is clicked and released, bg color changes respectively. Normal behaviour
Case II:- When Cell object is in "mode 2"
There are initially two frames in the frame.
When the label is clicked, bg color changes alright, but the frames suddenly disappear. The frames don't reappear, unless window is resized.
I doubted if the frames were sent behind of the Cell object (which seems absurd to me) and tried .lift()ing it. No success. Then I tried .update() and .update_idletasks() on the Cell object. No success again.
I want the frames to not disappear when I do .config(bg="new bg") and not need to resize the window just to make them reappear (don't know why this is needed)
Is this the way it is supposed to work - hiding the frames for some reason on configuring the label attributes? If so, what can be a way around it?
Minimal code attached below:
import tkinter as tk
def setMode1():
f1.place_forget()
f2.place_forget()
def setMode2():
f1.place(relwidth=1, relheight=0.1)
f2.place(relwidth=1, relheight=0.1, rely=0.9)
on_click = lambda event: Cell.config(bg="#9999CC")
on_release = lambda event: Cell.config(bg="#CCCCFF")
window = tk.Tk()
window.wm_geometry("240x380")
Cell = tk.Label(window, text="TEXT", bg="#CCCCFF")
Cell.bind("<Button-1>", on_click)
Cell.bind("<ButtonRelease-1>", on_release)
f1 = tk.Frame(Cell, bg="#66AAFF")
f2 = tk.Frame(Cell, bg="#66AAFF")
Cell.place(width=240, height=200, y=25)
tk.Button(window, text="Mode 1", command=setMode1).place(width=100, height=40, x=70, y=250)
tk.Button(window, text="Mode 2", command=setMode2).place(width=100, height=40, x=70, y=315)
window.mainloop()
(I had posted the same question earlier but realised it was way too verbose. This is a shorter version)
Any inputs to resolve the issue would be highly appreciated.
EDIT: Both - the alternate solution of the accepted answer, as well as the suggestion by #Eli Harold to tweak the config method of the class to un-place and re-place the frames - worked. However the accepted solution has accomplished it in its alternate solution without use of extra widgets/commands/tweaking.
Label is not designed for holding other widgets. Better use a frame to hold the label and the two frames instead:
import tkinter as tk
def setMode1():
f1.place_forget()
f2.place_forget()
def setMode2():
f1.place(relwidth=1, relheight=0.1)
f2.place(relwidth=1, relheight=0.1, rely=0.9)
on_click = lambda event: Cell.config(bg="#9999CC")
on_release = lambda event: Cell.config(bg="#CCCCFF")
window = tk.Tk()
window.wm_geometry("240x380")
# outer frame to hold the label and the two frames
container = tk.Frame(window)
container.place(width=240, height=200, y=25)
Cell = tk.Label(container, text="TEXT", bg="#CCCCFF")
Cell.place(relwidth=1, relheight=1)
Cell.bind("<Button-1>", on_click)
Cell.bind("<ButtonRelease-1>", on_release)
f1 = tk.Frame(container, bg="#66AAFF")
f2 = tk.Frame(container, bg="#66AAFF")
tk.Button(window, text="Mode 1", command=setMode1).place(width=100, height=40, x=70, y=250)
tk.Button(window, text="Mode 2", command=setMode2).place(width=100, height=40, x=70, y=315)
window.mainloop()
Another suggestion is create the two sub-frames children of window and use in_=Cell inside .place():
import tkinter as tk
def setMode1():
f1.place_forget()
f2.place_forget()
def setMode2():
# place inside Cell
f1.place(in_=Cell, relwidth=1, relheight=0.1)
f2.place(in_=Cell, relwidth=1, relheight=0.1, rely=0.9)
on_click = lambda event: Cell.config(bg="#9999CC")
on_release = lambda event: Cell.config(bg="#CCCCFF")
window = tk.Tk()
window.wm_geometry("240x380")
Cell = tk.Label(window, text="TEXT", bg="#CCCCFF")
Cell.bind("<Button-1>", on_click)
Cell.bind("<ButtonRelease-1>", on_release)
f1 = tk.Frame(window, bg="#66AAFF") # child of window instead
f2 = tk.Frame(window, bg="#66AAFF")
Cell.place(width=240, height=200, y=25)
tk.Button(window, text="Mode 1", command=setMode1).place(width=100, height=40, x=70, y=250)
tk.Button(window, text="Mode 2", command=setMode2).place(width=100, height=40, x=70, y=315)
window.mainloop()
The frames are just being pushed behind the background of the label. You can add some code like this to fix the issue:
import tkinter as tk
def setMode1():
global mode
f1.place_forget()
f2.place_forget()
mode = 1
def setMode2():
global mode
f1.place(relwidth=1, relheight=0.1)
f2.place(relwidth=1, relheight=0.1, rely=0.9)
mode = 2
on_click = lambda event: Cell.config(bg="#9999CC")
def on_release(event):
Cell.config(bg="#CCCCFF")
if mode == 2:
f1.place_forget()
f2.place_forget()
f1.place(relwidth=1, relheight=0.1)
f2.place(relwidth=1, relheight=0.1, rely=0.9)
mode = 0
window = tk.Tk()
window.wm_geometry("240x380")
Cell = tk.Label(window, text="TEXT", bg="#CCCCFF")
Cell.bind("<Button-1>", on_click)
Cell.bind("<ButtonRelease-1>", on_release)
f1 = tk.Frame(Cell, bg="#66AAFF")
f2 = tk.Frame(Cell, bg="#66AAFF")
Cell.place(width=240, height=200, y=25)
tk.Button(window, text="Mode 1", command=setMode1).place(width=100, height=40, x=70, y=250)
tk.Button(window, text="Mode 2", command=setMode2).place(width=100, height=40, x=70, y=315)
window.mainloop()
This just adds a variable mode that tells on_release how to treat the frames. It basically forces the program to add the frames when it needs to.
I am trying to open a toplevel window with a label from a function call but the label is not showing. What am I doing wrong?
Gratias.
from tkinter import *
import tkinter.font as fonte
def open_top():
top = Toplevel(master)
top.geometry("375x238+789+479")
top.resizable(width=FALSE, height=FALSE)
topFont = fonte.Font(family='Ubuntu', size=40)
label = Label(top, text='world', borderwidth=2, relief="sunk", width=24)
label.config(font = topFont, height=11, wraplength=350)
label.grid(row = 0, column = 0, columnspan=1, rowspan=1, sticky=W+E+N+S)
master.update()
# creating main tkinter window
master = Tk()
master.geometry("374x340+790+100")
master.resizable(width=FALSE, height=FALSE)
myFont = fonte.Font(family='Monospace', size=25)
view = Label(master, text='helo', borderwidth=2, relief="sunk", width=10)
view.config(font = ('Monospace', 36), height=3)
view.grid(row = 4, column = 0, columnspan=2, rowspan=1, sticky=W+E+N+S, padx=5, pady=5)
btn = Button(master, text ='toplevel', command = lambda: open_top())
btn.grid(row=6, column=0, columnspan=1, pady=4, padx=4)
btn = Button(master, text='Quit', command=master.destroy)
btn.grid(row=6, column=1, columnspan=1, pady=4, padx=4)
mainloop()
First about the problem:
When you create the label, you specify the width (and later) height arguments. Since your label contains text the units you pass as values to those arguments represent characters for width and lines for height (You can read about those attributes here)
#TheLizzard mention: wraplength's value also is in characters, and since you have set it to 350 and your font is not that small, it will wrap the text when a huge part of it is out of the window (and quite possibly even out of the screen) so with the current value it is quite useless. (it is also quite useless if you add static text because then you can simply add a newline or sth, a use case would be when you don't know how long the text is, for example, it was taken from user input)
Possible fixes:
Remove the width and height arguments (really the easiest):
label = Label(top, text='world', borderwidth=2, relief="sunk")
label.config(font=topFont, wraplength=350)
The widget can be also configured all at once, you don't need to use its method like this for initialization:
label = Label(top, text='world', borderwidth=2, relief="sunk", font=topFont, wraplength=350)
Change the height and width values (width tho really doesn't have to be used, especially if you use the wraplength argument):
label = Label(top, text='world', borderwidth=2, relief="sunk", font=topFont, wraplength=350, height=1)
Use anchor (really not that much of a fix or anything but will allow you to see the text (to an extent)):
label.config(anchor='nw')
Few other things:
Important (suggestions)
I strongly advise against using wildcard (*) when importing something, You should either import what You need, e.g. from module import Class1, func_1, var_2 and so on or import the whole module: import module then You can also use an alias: import module as md or sth like that, the point is that don't import everything unless You actually know what You are doing; name clashes are the issue.
Also: I strongly suggest following PEP 8 - Style Guide for Python Code. Function and variable names should be in snake_case, class names in CapitalCase. Don't have space around = if it is used as a part of keyword argument (func(arg='value')) but use if it is used for assigning a value (variable = 'some value'). Have two blank lines around function and class declarations.
Is it possible to make tkinter window's contents adjust to screen size? Like if I had made a window according to a screen resolution of 1366x768, and then I run the same code on a system of 1024x768 resolution and make its contents resize dynamically? I know I can use grid structure as as described here and set the weight of cells accordingly. But is it possible with pack geometry structure and not grid? I am asking this since half of the project I am working on was made by my colleague and he didn't use grid at all. So instead of redoing all of the code in grid, I am looking for a way around it. Here is the sample code I need to resize -
def container(self):
frame_number_panel = tk.Frame(self.parent, width=round(Dimension.SCREEN_WIDTH*0.8), height=Dimension.SCREEN_HEIGHT, bg="#eeeeee")
frame_number_panel.pack(side="left", anchor=W)
frame_number_panel.pack_propagate(False)
self.main_container(frame_number_panel)
# right side pannel
frame_right_side_panel = tk.Frame(self.parent, bg="#101115", width=round(Dimension.SCREEN_WIDTH*0.2), height=Dimension.SCREEN_HEIGHT)
frame_right_side_panel.pack(side="right", anchor=NE)
frame_right_side_panel.pack_propagate(False)
frame_first_row = tk.Frame(frame_right_side_panel, bg="#101115")
frame_first_row.pack()
winning_claim_image = PhotoImage(file=ResourcePath.resource_path('images/icon_win_claim.png'))
label_winning_claim = tk.Label(frame_first_row, bg="#fcd116", text="WINNING\nCLAIM", image=winning_claim_image,
compound="left", fg="#231f20", font=("Roboto-Bold", 10, "bold"),
width=Dimension.label_winning_claim_width,
height=Dimension.label_winning_claim_height)
label_winning_claim.image = winning_claim_image
label_winning_claim.pack(side="left", padx=Dimension.label_winning_claim_padx)
reprint_image = PhotoImage(file=ResourcePath.resource_path('images/reprint_2.png'))
label_reprint = tk.Label(frame_first_row, bg="#8ac539", text="REPRINT", image=reprint_image,
compound="left", fg="#231f20", font=("Roboto-Bold", 10, "bold"),
width=Dimension.label_winning_claim_width, height=Dimension.label_winning_claim_height)
label_reprint.image = reprint_image
label_reprint.pack(side="left", padx=Dimension.label_winning_claim_padding)
as you can see all the widgets are placed using pack geometry manager.
You can achieve nearly the same with pack than with grid. Indeed, I usually prefer the packing, since it gives me more freedom.
For instance, take the following example:
from tkinter import Tk, Label, X, Frame, Y, LEFT, BOTH
root = Tk()
# Initialize frames
f1 = Frame(root, bg="grey")
f2 = Frame(root, bg="pink")
# Initialize labels
w1 = Label(f1, text="Red", bg="red", fg="white")
w2 = Label(f1, text="Green", bg="green", fg="white")
w3 = Label(f1, text="Blue", bg="blue", fg="white")
w1b = Label(f2, text="Red", bg="red", fg="white")
w2b = Label(f2, text="Green", bg="green", fg="white")
w3b = Label(f2, text="Blue", bg="blue", fg="white")
# Packing level 1
f1.pack(fill=X)
f2.pack(fill=BOTH, expand=True)
# Packing level 2
w1.pack(fill=X)
w2.pack(fill=X)
w3.pack(fill=X)
w1b.pack(side=LEFT, fill=BOTH, expand=True)
w2b.pack(side=LEFT, fill=BOTH, expand=True)
w3b.pack(side=LEFT, fill=BOTH, expand=True)
root.mainloop()
As you can see, by using the parameters fill and expand in the correct way, I have set the second frame to be expandable with the windows on both sides (X and Y), while the first frame is only expandable in X. All the labels inside the frames are also equally distributed.
See all the options of pack in the documentation: https://effbot.org/tkinterbook/pack.htm.
I am building a GUI for a software and want to achieve this:
######################################
# | some title #
# menu upper |----------------------#
# | #
# | CANVAS #
# menu lower | #
# | #
#------------------------------------#
# statusbar #
######################################
Menu upper has some high level functionality, menu lower is changing in dependency of user input. Statusbar changes its contents often.
Unfortunately, Tkinter refuses to work.
Using the grid layout manager I were unable to create a stable design and adding content like labels and buttons to the menu on the left side:
self.root = tk.Tk()
self.root.resizable(width=0, height=0)
self.root.title("some application")
# menu left
self.menu_left = tk.Frame(self.root, width=150, bg="#ababab")
self.menu_left.grid(row=0, column=0, rowspan=2, sticky="ns")
self.menu_left_upper = tk.Frame(self.menu_left, width=150, height=150, bg="red")
self.menu_left_upper.grid(row=0, column=0)
# this label breaks the design
#self.test = tk.Label(self.menu_left_upper, text="test")
#self.test.pack()
self.menu_left_lower = tk.Frame(self.menu_left, width=150, bg="blue")
self.menu_left_lower.grid(row=1, column=0)
# right area
self.some_title_frame = tk.Frame(self.root, bg="#dfdfdf")
self.some_title_frame.grid(row=0, column=1, sticky="we")
self.some_title = tk.Label(self.some_title_frame, text="some title", bg="#dfdfdf")
self.some_title.pack()
self.canvas_area = tk.Canvas(self.root, width=500, height=400, background="#ffffff")
self.canvas_area.grid(row=1, column=1)
self.root.mainloop()
This design worked without contents in the menu on the left side. Whenever I added something in self.menu_left_upper or self.menu_left_lower, like the test label, my design got broke: the menu frames disappeared.
Additionally, even with columnspan, I had to remove the statusbar, because when it was added the menus on the left disappeared, again.
Using pack layout manager I got this:
######################################
# | some title #
# |----------------------#
# menu upper | #
# | CANVAS #
# | #
# menu lower | #
# |----------------------#
# | statusbar #
######################################
Since I wanted the menu frame on the left to consume the full y-space I made it grow with pack(side="left", expand=True, fill="both"), but this setup always denies the statusbar to go for the full width.
Besides, the pure pack manager code looks "ugly". I think a design with a grid manager is "clearer". Therefore I thought a grid or a pack layout inside a grid layout would be nice?
Can anyone help? I am stuck in the GUI-hell :/
The key to doing layout is to be methodical, and to use the right tool
for the job. It also means that sometimes you need to be creative.
That means using grid when laying things out in a
grid, and using pack when laying things out top-to-bottom or
left-to-right.
The other key is to group your layout code together. It's much, much
easier to visualize and modify the layout when it's all in one block
of code.
In your case you seem to have three or four distinct areas, depending
on how you count. If you want to use grid, it will be easiest to
combine "menu upper" and "menu lower" into a frame, and treat that
whole frame as a table cell. It looks like you're already doing that,
which is good.
So, let's start with those main areas:
self.menu_left.grid(row=0, column=0, rowspan=2, sticky="nsew")
self.some_title_frame.grid(row=0, column=1, sticky="ew")
self.canvas_area.grid(row=1, column=1, sticky="nsew")
# you don't have a status bar in the example code, but if you
# did, this is where you would put it
# self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")
Any time you use grid, you need to give at least one row and one
column a positive weight so that tkinter knows where to use any
unallocated space. Usually there is one widget that is the "main"
widget. In this case it's the canvas. You want to make sure that the
row and column for the canvas has a weight of 1 (one):
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_columnconfigure(1, weight=1)
note: using pack instead of grid would save you two lines of code, since pack doesn't require you to set weights the way grid does.
Next, we need to solve the problem of the menu areas. By default,
frames shrink to fit their contents, which is why adding the label
broke your layout. You weren't telling tkinter what to do with extra space, so the frames shrunk to fit, and extra space went unused.
Since you want "menu_upper" and "menu_lower" to
each share 50% of that area, pack is the simplest solution. You can
use grid, but it requires more lines of code to add the row and column weights.
self.menu_left_upper.pack(side="top", fill="both", expand=True)
self.menu_left_lower.pack(side="top", fill="both", expand=True)
Here is a functioning version, with statusbar. Notice how it behaves exactly as it should when you resize the window:
import Tkinter as tk
class Example():
def __init__(self):
self.root = tk.Tk()
self.root.title("some application")
# menu left
self.menu_left = tk.Frame(self.root, width=150, bg="#ababab")
self.menu_left_upper = tk.Frame(self.menu_left, width=150, height=150, bg="red")
self.menu_left_lower = tk.Frame(self.menu_left, width=150, bg="blue")
self.test = tk.Label(self.menu_left_upper, text="test")
self.test.pack()
self.menu_left_upper.pack(side="top", fill="both", expand=True)
self.menu_left_lower.pack(side="top", fill="both", expand=True)
# right area
self.some_title_frame = tk.Frame(self.root, bg="#dfdfdf")
self.some_title = tk.Label(self.some_title_frame, text="some title", bg="#dfdfdf")
self.some_title.pack()
self.canvas_area = tk.Canvas(self.root, width=500, height=400, background="#ffffff")
self.canvas_area.grid(row=1, column=1)
# status bar
self.status_frame = tk.Frame(self.root)
self.status = tk.Label(self.status_frame, text="this is the status bar")
self.status.pack(fill="both", expand=True)
self.menu_left.grid(row=0, column=0, rowspan=2, sticky="nsew")
self.some_title_frame.grid(row=0, column=1, sticky="ew")
self.canvas_area.grid(row=1, column=1, sticky="nsew")
self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_columnconfigure(1, weight=1)
self.root.mainloop()
Example()
On an unrelated note: I would strongly encourage you to not remove the ability for the user to resize the window. They know better than you what their requirements are. If you use grid and pack properly, the GUI will resize perfectly.
Adding the following code right before self.root.mainloop() achieves what you're looking for
self.some_status = tk.Label(self.root, text="status bar", bg="#dfdfdf")
self.some_status.grid(row=3, column=0, columnspan=2, sticky="we")
By putting in the line:
menu_left_upper.grid_propagate(False)
In between your menu_left_upper Frame and menu_left_upper.mainloop()
This works as:
By default, a container widget expands or collapses to be just big enough to hold its contents. Thus, when you call pack, it causes the frame to shrink. This feature is called geometry propagation.
For the vast majority of applications, this is the behavior you want. For those rare times when you want to explicitly set the size of a container you can turn this feature off. To turn it off, call either pack_propagate or grid_propagate on the container (depending on whether you're using grid or pack on that container), giving it a value of False.
See link to another question where this came from
To get your status bar just implement another frame and grid method:
status_bar_frame = Frame(root, bg="#dfdfdf")
status_bar_frame.grid(row=3, column=0, columnspan=2, sticky="we")
status_bar = Label(status_bar_frame, text="status bar", bg="#dfdfdf")
status_bar.pack()
Then your plan works.
Hope it helps :)
PS. Also why all the self attributes?
EDIT:
TO work you need to do:
menu_left_upper = Frame(menu_left, width=225, height=225, bg="red")
menu_left_upper.grid_propagate(False)
menu_left_upper.grid(row=0, column=0)
# this label breaks the design
test = Label(menu_left_upper, text="test", bg='red')
test.grid()
My result
I create a LabelFrame widget. It has a nice size in the beginning:
import Tkinter
form = Tkinter.Tk()
errorArea = Tkinter.LabelFrame(form, text=" Errors ", width=250, height=80)
errorArea.grid(row=2, column=0, columnspan=2, sticky="E", \
padx=5, pady=0, ipadx=0, ipady=0)
But when I insert an empty string in it, the errorArea widget's size adjusts according to the inserted string:
errorMessage = Tkinter.Label(errorArea, text="")
errorMessage.grid(row=0, column=0, padx=5, pady=2, sticky='W')
How do I give the errorArea widget a fixed size, so that its size won't change according to Lable inserted in it?
That problem always was interesting to me. One way I found to fix it is by using the place method instead of grid:
import Tkinter
form = Tkinter.Tk()
errorArea = Tkinter.LabelFrame(form, text=" Errors ", width=250, height=80)
errorArea.grid(row=2, column=0, columnspan=2, sticky="E", \
padx=5, pady=0, ipadx=0, ipady=0)
errorMessage = Tkinter.Label(errorArea, text="")
# 1) 'x' and 'y' are the x and y coordinates inside 'errorArea'
# 2) 'place' uses 'anchor' instead of 'sticky'
# 3) There is no need for 'padx' and 'pady' with 'place'
# since you can specify the exact coordinates
errorMessage.place(x=10, y=10, anchor="w")
form.mainloop()
With this, the label is placed in the window without shrinking the labelframe.
If you use a sticky value that sticks the widget to all four sides of its cell rather than just one side, it won't shrink when you put a small label widget in it.
Another option is to call errorArea.grid_propagate(False), which tells the grid area not to shrink or expand to fit its contents. This will often result in undesirable resize behavior, or at least require you to do a little extra work to get the right resize behavior.
Use the grid function immediately after declaring the Labelframe.
EX :
String_l = ttk.Labelframe(pw, text='String',width=100, height=408).grid(column=1, row=0, padx=4, pady=4,rowspan=2)