Unable to generate tkinter scrollbar - python

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)

Related

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()

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

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

tkinter Frame not filling parent Canvas [duplicate]

So I've been using the canvas widget in tkinter to create a frame full of labels which has a scrollbar. All is working good except that the frame only expands to the size of the labels placed in it - I want the frame to expand to the size of the parent canvas.
This can easily be done if I use pack(expand = True) (which I have commented out in the code below) for the frame in the canvas but then then the scrollbar doesn't work.
Here's the appropriate bit of code:
...
self.canvas = Canvas(frame, bg = 'pink')
self.canvas.pack(side = RIGHT, fill = BOTH, expand = True)
self.mailbox_frame = Frame(self.canvas, bg = 'purple')
self.canvas.create_window((0,0),window=self.mailbox_frame, anchor = NW)
#self.mailbox_frame.pack(side = LEFT, fill = BOTH, expand = True)
mail_scroll = Scrollbar(self.canvas, orient = "vertical",
command = self.canvas.yview)
mail_scroll.pack(side = RIGHT, fill = Y)
self.canvas.config(yscrollcommand = mail_scroll.set)
self.mailbox_frame.bind("<Configure>", self.OnFrameConfigure)
def OnFrameConfigure(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
I've also provided an image with colored frames so you can see what I'm getting at. The pink area is the canvas that needs filling by the mailbox_frame (You can see the scrollbar on the right):
Just for future reference in case anyone else needs to know:
frame = Frame(self.bottom_frame)
frame.pack(side = LEFT, fill = BOTH, expand = True, padx = 10, pady = 10)
self.canvas = Canvas(frame, bg = 'pink')
self.canvas.pack(side = RIGHT, fill = BOTH, expand = True)
self.mailbox_frame = Frame(self.canvas, bg = 'purple')
self.canvas_frame = self.canvas.create_window((0,0),
window=self.mailbox_frame, anchor = NW)
#self.mailbox_frame.pack(side = LEFT, fill = BOTH, expand = True)
mail_scroll = Scrollbar(self.canvas, orient = "vertical",
command = self.canvas.yview)
mail_scroll.pack(side = RIGHT, fill = Y)
self.canvas.config(yscrollcommand = mail_scroll.set)
self.mailbox_frame.bind("<Configure>", self.OnFrameConfigure)
self.canvas.bind('<Configure>', self.FrameWidth)
def FrameWidth(self, event):
canvas_width = event.width
self.canvas.itemconfig(self.canvas_frame, width = canvas_width)
def OnFrameConfigure(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
Set a binding on the canvas <Configure> event, which fires whenever the canvas changes size. From the event object you can get the canvas width and height, and use that to resize the frame.
Just an updated answer which covers both horizontal and vertical scrollbars without breaking them.
def FrameWidth(self, event):
if event.width > self.mailbox_frame.winfo_width():
self.canvas.itemconfig(self.canvas_frame, width=event.width-4)
if event.height > self.mailbox_frame.winfo_height():
self.canvas.itemconfig(self.canvas_frame, height=event.height-4)
Only sets the frame height and width if they are less than the canvas width. Respects both Horizontal and Vertical scrollbars.

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()

Creating Frame inside a Canvas

I am trying to make a frame scrollable, and the only way I found to do this is making a scrollable canvas and adding a frame to it. This would work fine, if it worked for me.
I am able to create a scrollable canvas that works fine, but I can't seem to properly add a frame inside of it:
self.title = Label(root, text="Brnr", font=("Helvetica", 50), anchor = W, pady = 40, padx = 50)
self.title.pack (anchor = NW)
#creates title widget for title
self.frame = Frame(screen, bd =1)
self.frame.pack(fill = BOTH)
#Creates frame widget under which all other widgets will be kept
self.canvas = Canvas(self.frame, bd=1,scrollregion=(0,0, 1000, 1000), height = 600)
#creates canvas so that screen can be scrollable
self.scrollbar = Scrollbar(self.frame, command=self.canvas.yview)
#creates scrollbar
self.canvas.config(yscrollcommand=self.scrollbar.set)
#connects the scrollbar to the canvas
self.scrollbar.pack(side=RIGHT, fill=Y)
self.canvas.pack(expand=YES, fill=BOTH)
#packs the scrollbar and canvas so that they fill the remainder of the screen
self.frameC = Frame(bg = "red")
self.canvas.create_window(0,0, anchor = NW, window = self.frameC, width = 200, height = 200)
#creates window on the scrollable area to add other widgets
self.frameC.pack()
self.groupRec = LabelFrame(self.frameC, text ="Recommendations:", font=("Helvetica", 20))
self.groupRec.pack()
self.signupButton = Button(self.groupRec, text="Sign Up", width=10)
self.signupButton.pack(side=RIGHT)
#creates button to submit login
This gives me a scrollable, but empty, canvas, with none of the labelframe/button appearing.
By default, when you add a window to a canvas, the center of the window will be at the coordinates you give. Thus, the center of your frame will be at 0,0 which is the upper-left corner of the canvas. You can't see the widgets because they are outside the borders of the canvas.
The solution is to include anchor="nw" in the call to create_window, which will place the upper-left corner of your frame in the upper left corner of your canvas.
Don't forget to set the scroll region of the canvas to match the size of your frame. The easiest way to do that is with the command self.canvas.config(scrollregion=self.canvas.bbox("all")). You'll probably also need to add a binding to <Configure> on the canvas so that you can resize the inner frame when the user resizes the window. That's not always necessary, it depends a bit on exactly what you are trying to accomplish.
Here's a pro tip: to debug problems like this it's really helpful to temporarily give your frame and canvas different colors to more easily visualize what is happening.
Don't re-invent the wheel. Install Pmw (Python meta-widgets), assuming you are using Tkinter, http://pmw.sourceforge.net/ and use Pmw.ScrolledFrame.

Categories