tkinter useing grid on a frame doesn't seem to work - python

Im trying to get a tkinter gui that lets the user sign in im really new to tkinter. I made a frame and when i use grid to put another frame widget inside of the frame it does it based off of the root and not the inner_frame thats what I think is happening. In the code I made a grey box to demonstrate and I dont understand why it is below the blue frame and not inside the yellow frame under the "sign in" text. Thanks for the help.
from tkinter import *
root = Tk()
root.title("sighn in test")
#colors
background = "#273E47"
accent = "#d8973c"
red = "#bb4430"
white = "#edf2f4"
#this creates and places the background frame
main_buttons_frame = Frame(root, height = 500, width = 400, bg = background).grid(row = 0, column = 0)
#this creates and places the inner frame
inner_frame = Frame(main_buttons_frame, height = 450, width = 300, bg = accent).grid(row = 0, column = 0)
#this creates and places the "sighn in text"
top_text = Label(inner_frame, text = "sign in", font = ("helvitica", 30, "bold"), bg = accent, fg =
background).grid(row = 0, column = 0)
#this is a test to demonstrate
test_frame = Frame(inner_frame, bg = "grey", height = 100, width = 100).grid(row = 1, column = 0)
root.mainloop()

You have very common mistake of beginners
inner_frame = Frame(...).grid...()
It assigns None to inner_frame because grid()/pack()/place() gives None.
So later Frame(inner_frame, ..) means Frame(None, ..) and it adds to root
You have to do it in two steps
inner_frame = Frame(...)
inner_frame.grid(...)
And now you have Frame assigned to inner_frame
EDIT:
With correctly assigned widgets I get
and now gray box is inside yellow frame but image shows different problem - grid()/pack() automatically calculate position and size and external frame automatically change size to fit to child's size.
Using .grid_propagate(False) you can stop it
But it shows other problem - cells don't use full size of parent so yellow frame is moved to left top corner, not centered :) Empty cells have width = 0 and heigh = 0 so moving all to next row and next column will not change it - it will be still in left top corner :)
You need to assign weight to column and/or row which decide how to use free space. All columns/rows has weight=0 and when you set weight=1 then this row and/or column will use all free space - (this would need better explanation) - and then element inside cell will be centered.
main_buttons_frame.grid_columnconfigure(0, weight=1)
main_buttons_frame.grid_rowconfigure(0, weight=1)
import tkinter as tk # PEP8: `import *` is not preferred
# --- colors ---
background = "#273E47"
accent = "#d8973c"
red = "#bb4430"
white = "#edf2f4"
# --- main ---
root = tk.Tk()
root.title("sighn in test")
main_buttons_frame = tk.Frame(root, height=500, width=400, bg=background) # PEP8: without spaces around `=` inside `( )`
main_buttons_frame.grid(row=0, column=0)
#main_buttons_frame = None
main_buttons_frame.grid_propagate(False)
main_buttons_frame.grid_columnconfigure(0, weight=1)
main_buttons_frame.grid_rowconfigure(0, weight=1)
inner_frame = tk.Frame(main_buttons_frame, height=450, width=300, bg=accent)
inner_frame.grid(row=0, column=0)
#inner_frame = None
inner_frame.grid_propagate(False)
inner_frame.grid_columnconfigure(0, weight=1)
inner_frame.grid_rowconfigure(0, weight=1)
top_text = tk.Label(inner_frame, text="sign in", font=("helvitica", 30, "bold"), bg=accent, fg=background)
top_text.grid(row=0, column=0,)
#top_text = None
#top_text.grid_propagate(False)
#top_text.grid_columnconfigure(0, weight=1)
#top_text.grid_rowconfigure(0, weight=1)
test_frame = tk.Frame(inner_frame, bg="grey", height=100, width=100)
test_frame.grid(row=1, column=0)
#test_frame = None
#test_frame.grid_propagate(False)
#test_frame.grid_columnconfigure(1, weight=1)
#test_frame.grid_rowconfigure(0, weight=1)
root.mainloop()
BTW: PEP 8 -- Style Guide for Python Code

Related

How to make a floating Frame in tkinter

For my tkinter app I want to make a frame that would on top of other widgets, not taking any space (like html position fixed).
The Frame will have to contain widgets, if Frame is not possible labels or buttons will do.
I have no idea how to do it so haven't tried anything yet. Please help!
Here is a demonstration of place manager.
Remarks in the code explain behaviour.
import tkinter as tk
root = tk.Tk()
root.geometry("868x131")
button = tk.Button(root, text = "A Button")
button.place(x = 2, y = 2)
Frame = tk.LabelFrame(root, text = "A LabelFrame using place", bg="cyan")
# Frame using place with x, y, width, height in absolute coordinates
Frame.place(x = 250, y = 20, width = 600, height = 70)
ButtonInFrame = tk.Button(Frame, text = "A Button IN LabelFrame", bg="white")
# Note: place x,y is referenced to the container (Frame)
# Note: place uses just x,y and allows Button to determine width and height
ButtonInFrame.place(x = 2, y = 2)
Label = tk.Label(root, text = "A Label on LabelFrame\nWith multiple lines\nOf Text.", bg="light green")
# Label sits on top of buttonFrame and Frame
# Note place uses just x,y and allows Label to determine width and height
Label.place(x = 330, y = 60)
root.mainloop()

trying to freeze the labels only while moving horizontally (not while moving vertically) in tkinter GUI

There is a master window named top_wl. And frame_wl is created in it.
I have set of labels that are created in a frame_wl (which is on a canvas_wl) and also I am creating another small frame (fram_s) in master window (top_wl) which is on the separate canvas( canvas_s). another frame is created in the canvas_s ( named frame_s1). And i have created one label on fram_s( small frame). have set one horizontal scroll bar for canvas_wl alone .I have set both the canvas_wl and canvas_s on single vertical scroll bar (named : scroll_bar_v). The idea behind this is to freeze the labels in the small frame while moving horizontally where as it has moved with vertical scroll bar.
Now the problem is the labels on the small frame ( fram_s) is freezed on both vertical and horizontal movement. can some body help me to solve the problem? or please tell me where I am going wrong ?
top_wl = tk.Tk()# tk.Tk()
top_wl.title("Work Shop Layout")
fram_wl =tk.Frame(top_wl,width=1500,height=5000,bg = 'khaki1',relief= SUNKEN)
# Creating small frame
fram_s = tk.Frame(top_wl,width = 300,height = 500,bg = 'sky blue')
fram_s.place( x = 15, y = 90)
canvas_s = tk.Canvas(fram_s)
frame_s1 = tk.Frame(canvas_s)
l_12 = tk.Label(fram_s, text = 'Hello There',bd = 2, width = 30,bg = 'white',font = ('Arial',10,'bold'),relief = "solid")
l_12. place(x = 10, y = 30)
# finished samll frame
canvas_wl = tk.Canvas(fram_wl,width=1500,height=4000,bg = 'lime green')
# top frame portion
scroll_bar_v = tk.Scrollbar(fram_wl,orient='vertical')
scroll_bar_v.config(command = canvas_wl.yview )
scroll_bar_h = Scrollbar(fram_wl,orient='horizontal')
scroll_bar_h.config(command = canvas_wl.xview)
scroll_bar_h.pack( side = BOTTOM, fill = X )
t1 = tk.Label(fram_wl)#, text = "Hello There: Number_1",width = 50,height = 100,bg = 'Sky blue',font = ('Arial',10,'bold'),relief = "sunken") #(x = 710, y = 50)
scroll_bar_v.pack( side = RIGHT, fill = Y )
t1.pack(side = RIGHT)
scrollable_frame_wl = tk.Frame(canvas_wl,bg = 'moccasin')#, bg = 'cyan2')
canvas_wl.create_window(0, 0, window=scrollable_frame_wl, anchor='nw')
left_wl = tk.Frame(scrollable_frame_wl, borderwidth=2, height = 5000,width = 10000,relief="sunken") #
left_wl. pack(side = 'left',padx=10, pady=10)
left_wl.pack_propagate(0)
scrollable_frame_wl.update()
canvas_s.configure(yscrollcommand = scroll_bar_h.set,scrollregion = canvas_s.bbox("all"))
canvas_s.create_window((0,0),window =frame_s1, anchor = 'nw' )
canvas_wl.configure(xscrollcommand= scroll_bar_h.set,yscrollcommand= scroll_bar_v.set,scrollregion=canvas_wl.bbox("all"))
canvas_wl.pack(fill = 'both')
fram_wl.pack()
top_wl.mainloop()
This code scroll vertically both canvas and horizontally only bigger canvas.
There was mess in code so I organized code in different way to make some order.
First create scrollbars (which will be used by both canvas)
Next I create bigger frame with canvas and inner frame.
Next in the same way I create smaller frame with canvas and inner frame.
Next I add some elements to inner frames - in both I add label at the top and at the bottom of inner frame. This way I will see if it scroll to the end.
And finally I assign scrollbars to canvas to move them. Next I assign canvas to scrollbars to resize scrollbars to correct size.
And it works
There is only one problem. At this moment both frames shows only 1/3 of canvas height - so vertical scrollbar need to show slider with the same size (1/3 height) - but when you resize window then bigger frame show more canvas and scrollbar also show longer slider but smaller frame still show 1/3 of canvas and it would need smaller slider - and it would make conflict. It would display longer slider for short time (for bigger frame) and next longer slider for longer time (for shorter frame). Resizing also makes problem when you scroll down - first it shows bottom label in bigger frame but it still need mouse move to show bottom label in smaller frame.
I don't see good solution for this conflict - eventually you would have to resize smaller frame to show the same proporiton of canvas.
import tkinter as tk
top_wl = tk.Tk()
top_wl.title("Work Shop Layout")
# --- scrolls outside big frame (directly in window) ---
scroll_bar_v = tk.Scrollbar(top_wl, orient='vertical')
scroll_bar_v.pack(side='right', fill='y')
scroll_bar_h = tk.Scrollbar(top_wl, orient='horizontal')
scroll_bar_h.pack(side='bottom', fill='x')
# --- big frame (directly in window) ---
# external frame
fram_wl = tk.Frame(top_wl, width=500, height=500, bg='khaki1', relief='sunken')
fram_wl.pack(side='right', expand=True, fill='both')
fram_wl.pack_propagate(False) # don't resize external frame to canvas size
# inne canvas with size bigger then external frame
canvas_wl = tk.Canvas(fram_wl, width=1500, height=1500, bg='lime green')
canvas_wl.pack(fill='both')
# inner frame with size bigger then frame (scrollbars will use this size to scroll it)
scrollable_frame_wl = tk.Frame(canvas_wl, width=1500, height=1500, bg='moccasin')#, bg = 'cyan2')
canvas_wl.create_window(0, 0, window=scrollable_frame_wl, anchor='nw')
# --- small frame (inside big frame so it doesn't hide scrollbars when window is smaller) ---
# external frame
#fram_s = tk.Frame(top_wl, width=300, height=300, bg='sky blue') # when it is directly in top_wl then it may hide scrollbars when window is smaller
fram_s = tk.Frame(fram_wl, width=300, height=300, bg='sky blue')
fram_s.place(x=0, y=100)
fram_s.pack_propagate(False) # don't resize external frame to canvas size
# inne canvas with size bigger then external frame
canvas_s = tk.Canvas(fram_s, width=900, height=900, bg='blue')
canvas_s.pack()
# inner frame with size bigger then frame (scrollbars will use this size to scroll it)
scrollable_frame_s = tk.Frame(canvas_s, width=900, height=900, bg='red')#, bg = 'cyan2')
canvas_s.create_window(0, 0, window=scrollable_frame_s, anchor='nw')
# ---
# add to inner frame in frame WL
label_wl_1 = tk.Label(scrollable_frame_wl, text='WL-Frame Top', bd=2, width=30, bg='white', font=('Arial', 10, 'bold'), relief="solid")
label_wl_1.place(x=10, y=30)
label_wl_2 = tk.Label(scrollable_frame_wl, text='WL-Frame Bottom', bd=2, width=30, bg='white', font=('Arial', 10, 'bold'), relief="solid")
label_wl_2.place(x=10, y=1500-30)
#label_wl_1.pack()
# add to inner frame in frame S
label_s_1 = tk.Label(scrollable_frame_s, text='S-Frame Top', bd=2, width=30, bg='white', font=('Arial', 10, 'bold'), relief="solid")
label_s_1.place(x=10, y=30)
label_s_2 = tk.Label(scrollable_frame_s, text='S-Frame Bottom', bd=2, width=30, bg='white', font=('Arial', 10, 'bold'), relief="solid")
label_s_2.place(x=10, y=900-30)
#label_s_1.pack()
# --- set scrollbars to move canvas ---
# to scroll vertically both canvas
def scroll_two_canvas(*args):
#print(args)
canvas_s.yview(*args)
canvas_wl.yview(*args)
scroll_bar_v.config(command=scroll_two_canvas) # it has to scroll two canvas
# to scroll horizontally one one canvas
scroll_bar_h.config(command=canvas_wl.xview) # it scroll only one canvas
# --- set canvas to resize scrollbars ---
# to update scrollbars when canvas is moved
canvas_wl.configure(xscrollcommand=scroll_bar_h.set)
canvas_wl.configure(yscrollcommand=scroll_bar_v.set)
# do't use it because it will conflict with previous
#canvas_s.configure(yscrollcommand=scroll_bar_v.set)
# get current size of element on canvas - if elements on canvas may change size (inner frame can change size) then you may need `bind('<Configure>')`
canvas_wl.configure(scrollregion=canvas_wl.bbox("all"))
canvas_s.configure(scrollregion=canvas_s.bbox("all"))
#def update_config(event):
# print(event)
# canvas_wl.configure(scrollregion=canvas_wl.bbox("all"))
# canvas_s.configure(scrollregion=canvas_s.bbox("all"))
#top_wl.bind('<Configure>', update_config)
# ---
top_wl.mainloop()
EDIT:
Code which resize smaller frame when bigger frame changes height. This way both frames shows the same percent of canvas height and scrollbar works better.
import tkinter as tk
top_wl = tk.Tk()
top_wl.title("Work Shop Layout")
# --- scrolls outside big frame (directly in window) ---
scroll_bar_v = tk.Scrollbar(top_wl, orient='vertical')
scroll_bar_v.pack(side='right', fill='y')
scroll_bar_h = tk.Scrollbar(top_wl, orient='horizontal')
scroll_bar_h.pack(side='bottom', fill='x')
# --- big frame (directly in window) ---
# external frame
fram_wl = tk.Frame(top_wl, width=500, height=500, bg='khaki1', relief='sunken')
fram_wl.pack(side='right', expand=True, fill='both')
fram_wl.pack_propagate(False) # don't resize external frame to canvas size
# inne canvas with size bigger then external frame
canvas_wl = tk.Canvas(fram_wl, width=1500, height=1500, bg='lime green')
canvas_wl.pack(fill='both')
# inner frame with size bigger then frame (scrollbars will use this size to scroll it)
scrollable_frame_wl = tk.Frame(canvas_wl, width=1500, height=1500, bg='moccasin')#, bg = 'cyan2')
canvas_wl.create_window(0, 0, window=scrollable_frame_wl, anchor='nw')
# --- small frame (inside big frame so it doesn't hide scrollbars when window is smaller) ---
# external frame
#fram_s = tk.Frame(top_wl, width=300, height=300, bg='sky blue') # when it is directly in top_wl then it may hide scrollbars when window is smaller
fram_s = tk.Frame(fram_wl, width=300, height=300, bg='sky blue')
fram_s.place(x=0, y=100)
fram_s.pack_propagate(False) # don't resize external frame to canvas size
# inne canvas with size bigger then external frame
canvas_s = tk.Canvas(fram_s, width=900, height=900, bg='blue')
canvas_s.pack()
# inner frame with size bigger then frame (scrollbars will use this size to scroll it)
scrollable_frame_s = tk.Frame(canvas_s, width=900, height=900, bg='red')#, bg = 'cyan2')
canvas_s.create_window(0, 0, window=scrollable_frame_s, anchor='nw')
# ---
# add to inner frame in frame WL
label_wl_1 = tk.Label(scrollable_frame_wl, text='WL-Frame Top', bd=2, width=30, bg='white', font=('Arial', 10, 'bold'), relief="solid")
label_wl_1.place(x=10, y=30)
label_wl_2 = tk.Label(scrollable_frame_wl, text='WL-Frame Bottom', bd=2, width=30, bg='white', font=('Arial', 10, 'bold'), relief="solid")
label_wl_2.place(x=10, y=1500-30)
#label_wl_1.pack()
# add to inner frame in frame S
label_s_1 = tk.Label(scrollable_frame_s, text='S-Frame Top', bd=2, width=30, bg='white', font=('Arial', 10, 'bold'), relief="solid")
label_s_1.place(x=10, y=30)
label_s_2 = tk.Label(scrollable_frame_s, text='S-Frame Bottom', bd=2, width=30, bg='white', font=('Arial', 10, 'bold'), relief="solid")
label_s_2.place(x=10, y=900-30)
#label_s_1.pack()
# --- set scrollbars to move canvas ---
# to scroll both canvas
def scroll_two_canvas(*args):
#print(args)
canvas_s.yview(*args)
canvas_wl.yview(*args)
scroll_bar_v.config(command=scroll_two_canvas) # it has to scroll two canvas
scroll_bar_h.config(command=canvas_wl.xview) # it scroll only one canvas
# --- set canvas to resize scrollbars ---
# to update scrollbars when canvas is moved
canvas_wl.configure(xscrollcommand=scroll_bar_h.set)
canvas_wl.configure(yscrollcommand=scroll_bar_v.set)
# do't use it because it will conflict with previous
#canvas_s.configure(yscrollcommand=scroll_bar_v.set)
# get current size of element on canvas - if elements on canvas may change size (inner frame can change size) then you may need `bind('<Configure>')`
canvas_wl.configure(scrollregion=canvas_wl.bbox("all"))
canvas_s.configure(scrollregion=canvas_s.bbox("all"))
# --- resize smaller frame when bigger frame changes height
# to keep current height and compare with new height when resize, and to calculate scale used to resize smaller framer
frame_wl_height = fram_wl['height']
def update_config(event):
global frame_wl_height
if event.widget == fram_wl: #'.':
scale = event.height/frame_wl_height
frame_wl_height = event.height
fram_s['height'] = fram_s['height'] * scale
#canvas_wl.configure(scrollregion=canvas_wl.bbox("all"))
#canvas_s.configure(scrollregion=canvas_s.bbox("all"))
top_wl.bind('<Configure>', update_config)
# ---
top_wl.mainloop()

Why are my Tkinter column widths misaligned?

I made an Excel-like grid for entering data that will be exported to another program. The top row is "frozen" so that it remains visible when you scroll down. I'm using a list ColWidths = [15, 15, 40] to define the widths of the widgets in the top row, and the widgets in the scroll-able rows beneath.
I read that if you don't give a unit, width defaults to pixels. Even so, I made sure to use the same font size in the top row and all the other rows.
Oddly the columns still appear to be slightly different widths. Any idea how to fix this?
MCVE CODE:
import tkinter as tk
from tkinter import simpledialog,filedialog,colorchooser,messagebox,Frame,Button
from PIL import ImageTk, Image
import textwrap
root = tk.Tk()
canv_1 = tk.Canvas(root, bg="blue")
canv_1.pack(side="top", fill="both")#, fill="both", expand=True)
canv_2 = tk.Canvas(root, bg="gray")
canv_2.pack(fill="both", expand=True)
def onFrameConfigure(canvas):
'''Reset the scroll region to encompass the inner frame'''
canvas.configure(scrollregion=canvas.bbox("all"))
frame = tk.Frame(canv_2)
# create, bind & position scrollbar
vsb = tk.Scrollbar(canv_2, orient="vertical", command=canv_2.yview)
canv_2.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
canv_2.pack(side="left", fill="both", expand=True)
canv_2.create_window((0,0), window=frame, anchor="nw")
frame.bind("<Configure>", lambda event, canv_2=canv_2: onFrameConfigure(canv_2))
labels = ["Chapter Title", "Slide", "Instructions"]
ColWidths = [15, 15, 40]
root.label_wid = []
font1 = ("arial", 15, "bold")
load1 = Image.open("StartingImage.jpg")
root.render1 = ImageTk.PhotoImage(load1)
ch_text = []
for i in range(len(labels)):
root.label_wid.append(tk.Label(canv_1,
font=font1,
relief="raised",
text=labels[i],
width=ColWidths[i],
).grid(row=0, column=i, sticky="we"))
c1 = "#a9d08e"
c2 = "#8dd1bf"
Title_col = [
tk.Entry(
frame,
bg = c1,
width = ColWidths[0],
font = font1)
for y in range(0, 5)
]
Slide_col = [
tk.Entry(
frame,
bg = c2,
width = ColWidths[1],
font = font1)
for y in range(0, 5)
]
instruction_col = [
tk.Text(
frame,
bg="white",
wrap="word",
font=font1, width = ColWidths[2], height=10)
for y in range(0, 5)
]
for y in range(0, 5):
Title_col[y].grid(row=y + 1, column=0, sticky='news')
Slide_col[y].grid(row=y + 1, column=1, sticky='news')
instruction_col[y].grid(row=y+1, column=2, sticky='news')
bt1 = tk.Button(canv_1, text="Export", font=font1, bg="#f5b942")
bt1.grid(row=0, column=4)
load2 = Image.open("scroll-up-gray.png")
root.render2 = ImageTk.PhotoImage(load2)
load3 = Image.open("scroll-down.png")
root.render3 = ImageTk.PhotoImage(load3)
root.mainloop()
GUI SCREENSNIP:
Remove bold from your font or figure out how much to add to the image column (your original screen grab) to compensate. Seriously though, just remove bold from your font and watch it all magically work.
bold is adding extra pixels to all of your labels, and it isn't adding anything in all of those empty boxes. It took me like 2 hours to figure this out (lol)! I even rewrote your entire example much better and still couldn't get it to work ... until I realized that the instruction label was being forced out of the window bounds. Some kind of way that triggered the font format in my head. I simply removed bold and everything worked. I then re-copy/pasted your example and removed bold. It still worked.
I understand that you ultimately want to keep bold. You will have to use line-metrics or something more reliable than simply telling every column to be the same size. The main point is, at least now you know the culprit and why.
edit:
I also got it to work by doing the below instead. Unfortunately, I can't explain why this works. Obviously, I know that we are just adding an inner padding to each cell, but I don't understand why dividing the cell width by 2 works in every case. This may even cause problems later. I simply don't know, but in this example case it seems to work almost perfect.
for y in range(0, 5):
Title_col[y].grid(row=y + 1, column=0, sticky='news', ipadx=ColWidths[0]/2)
Slide_col[y].grid(row=y + 1, column=1, sticky='news', ipadx=ColWidths[1]/2)
instruction_col[y].grid(row=y+1, column=2, sticky='news', ipadx=ColWidths[2]/2)
edit 2:
If you want the results of the above code to appear absolutely perfect in line with the header columns, specify highlightthickness=0 in your canvas instances. This will remove the canvas borders, which are creating a tiny offset.
canv_1 = tk.Canvas(root, bg="blue", highlightthickness=0)
canv_1.pack(side="top", fill="both")#, fill="both", expand=True)
canv_2 = tk.Canvas(root, bg="gray", highlightthickness=0)
canv_2.pack(fill="both", expand=True)

Unable to generate tkinter scrollbar

self.root = tkinter.Tk()
self.frame = Frame(self.root, width = 1300, height = 1300, bg = "yellow")
self.frame.grid(row = 0 , column = 0, sticky = 'nw')
self.frame.grid_rowconfigure(0, weight=1)
self.frame.grid_columnconfigure(0, weight=1)
self.frame.grid_propagate(True)
self.canvas_main = Canvas(self.frame,
height = 300,
width = 300,
scrollregion=(500,500,0,500)
)
self.canvas_main.grid(row = 0, column = 0, padx= 10, pady = 10, sticky = "news")
self.scrollbar = Scrollbar(self.root, orient = VERTICAL, command = self.canvas_main.yview)
self.scrollbar.grid(row = 0, column = 1, sticky = 'ns')
self.canvas_main.configure(yscrollcommand=self.scrollbar.set)
In above code block, I have entered Scrollbar element for enabling vertical scrollbar however, it does not reflect. Can anyone find out what I am doing wrong in this block?
You've set the scrollable region (scrollregion) to be zero pixels tall, so tkinter thinks there's nothing to be scrolled in the vertical direction.
Often you will do your drawing first and then set the scrollable region to encompass everything you've drawn. You do this by getting the bounding box -- the smallest rectangle that includes all of the canvas objects -- and then using that as the value for scrollregion.
Example:
canvas = tk.Canvas(...)
<draw a bunch of objects>
canvas.configure(scrollregion=canvas.bbox("all"))
The other method is to define ahead of time how big the virtual drawing area is. For example, you've set your canvas to have a width and height of 300. If you want the actual drawing area to be twice the visible size then you could set the scrollregion to an area twice that big.
This example sets the scrollable region to begin at 0,0 (the upper left corner), and extend to 600,600 (the bottom right corner):
canvas = tk.Canvas(..., width=300, height=300)
canvas.configure(scrollregion=(0,0,600,600)

tkinter pack doesn't expand through whole area

Having issues packing two frames to get an expected outcome as defined below:
Frame 1 to have a width of 150 and scale on Y value, color of blue.
Frame 2 to scale on both X and Y, color of red.
So that when the window is resized the frame 1 keeps its x position and the frame 2 will scale.
As seen in picture below:
Expected Outcome
So this was the code used:
import tkinter as tk
frame1 = tk.Frame(bg = 'blue', width= 150, height = 150)
frame2 = tk.Frame(bg = 'red')
frame1.pack(fill = tk.Y, expand = 1, anchor = tk.W, side = tk.LEFT)
frame2.pack_propagate(True)
frame2.pack(fill = tk.BOTH, expand = 1, anchor = tk.E, side = tk.RIGHT)
Though it produces this: Actual Outcome
A requirement for this is I still need to use pack, but stuck on how to get the outcome required.
Your only problem is that frame1 needs expand to be set to False or 0.
By setting it to 1, you're asking Tkinter to expand the area given to the left frame. Since you only have it fill in the "y" direction, the frame on the left doesn't fill up that extra area even though it has been allocated, which is why you see the blank space between the left and the right side.
fairly simple, if you want them to stack side by side you need to keep stacking them from the same side, and the first frame doesn't need expand=1
try the following:
import tkinter as tk
root = tk.Tk()
frame1 = tk.Frame(bg = 'blue', width= 150, height = 150)
frame2 = tk.Frame(bg = 'red')
frame1.pack(fill = tk.Y, anchor = tk.W, side = tk.LEFT)
frame2.pack_propagate(True)
frame2.pack(fill = tk.BOTH, expand = 1, anchor = tk.E, side = tk.LEFT)
root.mainloop()

Categories