Tinker Scrollbar not working with canvas widget - python

I can't for the life of me figure out why this is not working? I'm just trying to get a canvas to scroll with scrollbars.
I've followed #BryanOakley's advice to the question Tkinter Scrollbar not working but I can't seem to figure out what I am doing wrong.
Here is my code:
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master, bg= "#E3E5E6")
self.master = master
self.grid(sticky = "nesw")
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
self.canvas = tk.Canvas(master)
self.canvas.create_oval(10, 10, 20, 20, fill="red")
self.canvas.create_oval(200, 200, 220, 220, fill="blue")
self.canvas.grid(row=0, column=0, sticky = "nesw")
self.scroll_x = tk.Scrollbar(master, orient="horizontal", command=self.canvas.xview)
self.scroll_x.grid(row=1, column=0, sticky="ew")
self.scroll_y = tk.Scrollbar(master, orient="vertical", command=self.canvas.yview)
self.scroll_y.grid(row=0, column=1, sticky="ns")
self.canvas.configure(yscrollcommand=self.scroll_y.set, xscrollcommand=self.scroll_x.set)
self.canvas.configure(scrollregion=self.canvas.bbox((0,0,15000,15000)))
if __name__ == "__main__":
root = tk.Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.geometry("{}x{}+0+0".format(600,400))
app = Application(master=root)
app.mainloop()
Any help is much appreciated.

Change this:
self.canvas.configure(scrollregion=self.canvas.bbox((0,0,15000,15000)))
To this:
self.canvas.configure(scrollregion=(0,0,15000,15000))
The scrollregion attribute requires a tuple of four coordinates. Calling bbox can return that tuple, but only if you give it an item id or a tag. You were feeding it a tuple, and since there was no item on the canvas that has a tag that looked like the tuple it was returning None.

Related

How to prevent multiple windows from popping up in tkinter?

import tkinter as tk
from tkinter import *
from tkinter import ttk
LARGE_FONT = ("Verdana", 12)
class pages(tk.Tk):
#starts us off in the login page
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "ScanNET")
tk.Tk.wm_minsize(self, 800, 800)
container = tk.Frame(self)
container.pack(side=TOP, fill=BOTH, expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (loginpage, GUI):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky=N+E+S+W)
self.show_frame(loginpage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class loginpage(tk.Frame):
#login page content
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
loginlabel = tk.Label(self, text="login page", font=LARGE_FONT)
loginlabel.pack(padx=10, pady=10)
#button moves you to gui
loginbutton1 = tk.Button(self, text= "Go to GUI", command=lambda: controller.show_frame(GUI))
loginbutton1.pack()
class GUI(tk.Frame):
def __init__(self, parent, controller):
#all widths and heights aren't official, most likely change
tk.Frame.__init__(self, parent)
self.root = tk.Tk()
#the tabs
my_notebook = ttk.Notebook(self.root)
my_notebook.pack()
devicestab = Frame(my_notebook, width=800, height=600)
reportstab = Frame(my_notebook, width=800, height=600)
devicestab.pack(fill=BOTH, expand=1)
reportstab.pack(fill=BOTH, expand=1)
my_notebook.add(devicestab, text="Devices")
my_notebook.add(reportstab, text="Reports")
#contents for devices tab
devicesleft = LabelFrame(devicestab, text="Devices found: ", padx=5, pady=5, width=500, height=600)
devicesleft.grid(row=0, column=0)
devicesright = LabelFrame(devicestab, text="Activity Feed: ", padx=5, pady=5, width=300 , height=600)
devicesright.grid(row=0, column=1)
#contents for reports tab
reportsleft = LabelFrame(reportstab, text="Report Summaries: ", padx=5, pady=5, width=400 , height=600)
reportsleft.grid(row=0, column=0)
reportsright= LabelFrame(reportstab, text="Charts and Diagrams: ", padx=5, pady=5, width=400 , height=600)
reportsright.grid(row=0, column=1)
app = pages()
app.mainloop()
When I run this, both the loginpage and GUI windows open. Correct me if I'm wrong, but I think the problem is probably around the
tk.Frame.__init__(self, parent)
self.root = tk.Tk()
my_notebook = ttk.Notebook(self.root)
part in the GUI class. I've searched everywhere and I can't seem to find a way to have a first page as a login page which will move to a second page that has tabs using notebook. I feel as if something else has to be in the ttk.Notebook() part, and perhaps remove self.root = tk.Tk() after. I'd love to hear what y'all think.
I am assuming you want the notebook in the same widget of the rest, so you should not use tk.Tk() and then you place the notebook in the parent which is already your root. Check the code in the end of my answer. Also, since there was a lot of problems with your code I made some changes and comments that will help you to write better codes in tkinter. Please read it carefully. You may also want to study the effbot web page.
import tkinter as tk
# from tkinter import * # just don't do this
from tkinter import ttk
LARGE_FONT = ("Verdana", 12)
# class pages(tk.Tk):
class Pages(tk.Tk): # class names should start with upper case
#starts us off in the login page
# def __init__(self, *args, **kwargs):
def __init__(self):
# tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.__init__(self)
# tk.Tk.wm_title(self, "ScanNET")
self.winfo_toplevel().title("ScanNET")
# tk.Tk.wm_minsize(self, 800, 800)
self.wm_minsize(800, 800) # since you defined tk.Tk as pages parent you can call Tk methods directly
container = tk.Frame(self)
# container.pack(side=TOP, fill=BOTH, expand=True)
# container.grid_rowconfigure(0, weight=1)
# container.grid_columnconfigure(0, weight=1)
container.grid(row=0, column = 0) # don't use pack if you want to use grid
self.frames = {}
for F in (loginpage, GUI):
frame = F(container, self)
self.frames[F] = frame
# frame.grid(row=0, column=0, sticky=N+E+S+W)
frame.grid(row=0, column=0, sticky='NESW') #since we are not importing all we are not importing tk.W but you can use string instead
self.show_frame(loginpage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class loginpage(tk.Frame):
#login page content
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
loginlabel = tk.Label(self, text="login page", font=LARGE_FONT)
loginlabel.pack(padx=10, pady=10)
#button moves you to gui
loginbutton1 = tk.Button(self, text= "Go to GUI", command=lambda: controller.show_frame(GUI))
loginbutton1.pack()
class GUI(tk.Frame):
def __init__(self, parent, controller):
#all widths and heights aren't official, most likely change
tk.Frame.__init__(self, parent)
# self.root = tk.Tk() # don't create new Tk objects, you just need one. The others should be Toplevel objects
### self.root = tk.Toplevel() ### this would be the correct way of creating a new window but you don't want to do that here your root is your parent
#the tabs
# my_notebook = ttk.Notebook(self.root)
my_notebook = ttk.Notebook(self) # this is how you place the notebook in the Frame widget and not in a new one
# my_notebook.pack()
my_notebook.grid() # we are now using grid so it will not accept pack anymore
# devicestab = Frame(my_notebook, width=800, height=600)
devicestab = tk.Frame(my_notebook, width=800, height=600) # again, since we are not importing al we have to use tk. before tkinter methods
# reportstab = Frame(my_notebook, width=800, height=600)
reportstab = tk.Frame(my_notebook, width=800, height=600)
# devicestab.pack(fill=BOTH, expand=1)
devicestab.pack(fill="both", expand=1) # instead of tk.BOTH we can use "both"
reportstab.pack(fill="both", expand=1)
my_notebook.add(devicestab, text="Devices")
my_notebook.add(reportstab, text="Reports")
#contents for devices tab
devicesleft = tk.LabelFrame(devicestab, text="Devices found: ", padx=5, pady=5, width=500, height=600)
devicesleft.grid(row=0, column=0)
devicesright = tk.LabelFrame(devicestab, text="Activity Feed: ", padx=5, pady=5, width=300 , height=600)
devicesright.grid(row=0, column=1)
#contents for reports tab
reportsleft = tk.LabelFrame(reportstab, text="Report Summaries: ", padx=5, pady=5, width=400 , height=600)
reportsleft.grid(row=0, column=0)
reportsright= tk.LabelFrame(reportstab, text="Charts and Diagrams: ", padx=5, pady=5, width=400 , height=600)
reportsright.grid(row=0, column=1)
app = Pages()
app.mainloop()

Python Tkinter: Paned Window not sticking to top

Thanks for taking time to look at this. I've been struggling with this for almost a week and its driving me crazy.
I have a horizontal Paned Window which is supposed to stretch from the bottom of my toolbar to the bottom of my window, but it's sticking only to the bottom of the root window. Eventually I want to have a Treeview widget in the left pane and thumbnails in the right pane.
Can anyone help me to get the Paned Window to stick NSEW? Do I need to put it inside another frame?
I'm using Python 2.7 on Windows 7. (This isn't my whole program, just a sample to demonstrate the problem.)
#!/usr/bin/env python
# coding=utf-8
from Tkinter import *
from ttk import *
class MainWindow:
def null(self):
pass
def __init__(self):
self.root = Tk()
self.root.geometry("700x300")
self.root.resizable(width=TRUE, height=TRUE)
self.root.rowconfigure(0, weight=1)
self.root.columnconfigure(0, weight=1)
self.menubar = Menu(self.root)
File_menu = Menu(self.menubar, tearoff=0)
self.menubar.add_cascade(label="Pandoras Box", menu=File_menu)
File_menu.add_command(label="Black Hole", command=self.null)
self.root.config(menu=self.menubar)
self.toolbar = Frame(self.root, relief=RAISED)
self.toolbar.grid(row=0, column=0, sticky='NEW')
self.toolbar.grid_columnconfigure(0, weight=1)
self.toolbar.rowconfigure(0, weight=1)
dummy = Button(self.toolbar, text="Tool Button")
dummy.grid(row=0, column=0, sticky='EW')
Find = Label(self.toolbar, text="Search")
Search = Entry(self.toolbar)
Find.grid(row=0, column=5, sticky='E', padx=6)
Search.grid(row=0, column=6, sticky='E', padx=8)
self.info_column = Frame(self.root, relief=RAISED, width=100)
self.info_column.grid(row=0, column=5, rowspan=3, sticky='NSW')
self.info_column.grid_rowconfigure(0, weight=1)
self.info_column.grid_columnconfigure(0, weight=1)
self.rootpane = PanedWindow(self.root, orient=HORIZONTAL)
self.rootpane.grid(row=1, column=0, sticky='NS')
self.rootpane.grid_rowconfigure(0, weight=1)
self.rootpane.grid_columnconfigure(0, weight=1)
self.leftpane = Frame(self.rootpane, relief=RAISED)
self.leftpane.grid(row=0, column=0, sticky='NSEW')
self.rightpane = Frame(self.rootpane, relief=RAISED)
self.rightpane.grid(row=0, column=0, sticky='NSEW')
''' THESE BUTTONS ARE SUPPOSED TO BE INSIDE PANED WINDOW STUCK TO THE TOP!'''
but_left = Button(self.leftpane, text="SHOULD BE IN LEFT PANE UNDER TOOLBAR FRAME")
but_left.grid(row=0, column=0, sticky='NEW')
but_right = Button(self.rightpane, text="SHOULD BE IN RIGHT PANE UNDER TOOLBAR FRAME")
but_right.grid(row=0, column=0, sticky='NEW')
self.rootpane.add(self.leftpane)
self.rootpane.add(self.rightpane)
self.SbarMesg = StringVar()
self.label = Label(self.root, textvariable=self.SbarMesg, font=('arial', 8, 'normal'))
self.SbarMesg.set('Status Bar:')
self.label.grid(row=3, column=0, columnspan=6, sticky='SEW')
self.label.grid_rowconfigure(0, weight=1)
self.label.grid_columnconfigure(0, weight=1)
self.root.mainloop()
a = MainWindow()
Short answer: the space you see between the buttons and the toolbar frame is because you allow the row containing the toolbar to resize, instead of the row containing the PanedWindow... To get what you want, replace:
self.root.rowconfigure(0, weight=1)
with
self.root.rowconfigure(1, weight=1)
Other comments:
Try to avoid wildcard imports. In this case, it makes it difficult to differentiate between tk and ttk widgets
To allow resizing of widgets aligned using grid(), .rowconfigure(..., weight=x) must be called on the widget's parent not the widget itself.
background colors are very useful to debug alignment issues in tkinter.
Code:
import Tkinter as tk
import ttk
class MainWindow:
def __init__(self):
self.root = tk.Tk()
self.root.geometry("700x300")
self.root.resizable(width=tk.TRUE, height=tk.TRUE)
self.root.rowconfigure(1, weight=1)
self.root.columnconfigure(0, weight=1)
self.toolbar = tk.Frame(self.root, relief=tk.RAISED, bg="yellow")
self.toolbar.grid(row=0, column=0, sticky='NEW')
self.toolbar.columnconfigure(0, weight=1)
dummy = ttk.Button(self.toolbar, text="Tool Button")
dummy.grid(row=0, column=0, sticky='EW')
Find = tk.Label(self.toolbar, text="Search")
Search = ttk.Entry(self.toolbar)
Find.grid(row=0, column=5, sticky='E', padx=6)
Search.grid(row=0, column=6, sticky='E', padx=8)
self.info_column = tk.Frame(self.root, relief=tk.RAISED, width=100, bg="orange")
self.info_column.grid(row=0, column=5, rowspan=2, sticky='NSW')
self.rootpane = tk.PanedWindow(self.root, orient=tk.HORIZONTAL, bg="blue")
self.rootpane.grid(row=1, column=0, sticky='NSEW')
self.leftpane = tk.Frame(self.rootpane, bg="pink")
self.rootpane.add(self.leftpane)
self.rightpane = tk.Frame(self.rootpane, bg="red")
self.rootpane.add(self.rightpane)
''' THESE BUTTONS ARE SUPPOSED TO BE INSIDE PANED WINDOW STUCK TO THE TOP!'''
but_left = ttk.Button(self.leftpane, text="SHOULD BE IN LEFT PANE UNDER TOOLBAR FRAME")
but_left.grid(row=0, column=0, sticky='NEW')
but_right = ttk.Button(self.rightpane, text="SHOULD BE IN RIGHT PANE UNDER TOOLBAR FRAME")
but_right.grid(row=0, column=0, sticky='NEW')
self.label = tk.Label(self.root, text="Status:", anchor="w")
self.label.grid(row=3, column=0, columnspan=6, sticky='SEW')
self.root.mainloop()
a = MainWindow()

Tkinter, make scrollbar stick to canvas and not root?

I've got a working scrollbar and a canvas. Problem is that my canvas height and maybe even width are not the same dimensions as the root, but the scrollbar is attached to the root. Which looks odd. How can I make it stick to the canvas? So that I also may add an additional canvas with a scrollbar in the future.
self.canvas = Canvas(root, borderwidth=0, background="#c0c0c0",height= 150, width=500)
self.frameTwo = Frame(self.canvas, background="#ffffff")
self.vsb = Scrollbar(root, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left")
self.canvas.place(y=195)
self.canvas.create_window((4,4), window=self.frameTwo, anchor="w",
tags="self.frame")
self.frameTwo.bind("<Configure>", self.onFrameConfigure)
The best solution is to put your scrollbars and canvas in a frame specifically for that purpose.
Here's a complete working example:
import tkinter as tk
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# create a frame specifically for the canvas,
# and scrollbars, and let it control the border
self.canvas_frame = tk.Frame(self, borderwidth = 1, relief="sunken")
self.canvas = tk.Canvas(self.canvas_frame, borderwidth=0, highlightthickness=0,
background="white")
self.vsb = tk.Scrollbar(self.canvas_frame, orient="vertical",
command=self.canvas.yview)
self.hsb = tk.Scrollbar(self.canvas_frame, orient="horizontal",
command=self.canvas.xview)
self.canvas.configure(yscrollcommand=self.vsb.set,
xscrollcommand=self.hsb.set)
self.canvas.grid(row=0, column=0, sticky="nsew")
self.vsb.grid(row=0, column=1, sticky="ns")
self.hsb.grid(row=1, column=0, sticky="ew")
self.canvas_frame.rowconfigure(0, weight=1)
self.canvas_frame.columnconfigure(0, weight=1)
# add the canvas+scrollbars to the window
self.canvas_frame.pack(fill="both", expand=True)
if __name__== "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
By the way, in your code you're calling both pack and place on the canvas. It's pointless to call both -- only one or the other can affect the placement of the widget. When you call place after calling pack for the same widget, the effects of calling place will be completely forgotten.

frames layout with canvas using tkinter

I'm added canvas and a scroll bar to one of the frames in my script.
However somethings wrong cause the scroll bar is off (lower bottom is not visible) and the text I drew is off. Could anyone please tell me whats the problem ? I want the canvas to fill the whole frame (obviously without the scroll bar)
import sys
import os
if sys.version_info[0] < 3:
import Tkinter as tk
import ttk as ttk
else:
import tkinter as tk
import tkinter.ttk as ttk
#
# LeftMiddle
#
class LeftMiddle(tk.Frame):
def __init__(self, master=None):
self.parent = master
tk.Frame.__init__(self, self.parent, bg='bisque', borderwidth=1, relief="sunken")
self.__create_layout()
self.draw_text()
def __create_layout(self):
self.canvas = tk.Canvas(self, bg="green", relief=tk.SUNKEN)
self.canvas.config(width=20, height=10)
self.canvas.config(highlightthickness=0)
self.sbar = tk.Scrollbar(self, orient=tk.VERTICAL)
self.sbar.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas.pack(side=tk.LEFT, expand="YES", fill=tk.BOTH)
def draw_text(self):
self.canvas.create_text(0, 0, text='1234567890', fill='red')
self.canvas.create_text(0, 25, text='ABCDEFGH', fill='blue')
#
# MainWindow
#
class MainWindow(tk.Frame):
def __init__(self, master=None):
self.parent = master
tk.Frame.__init__(self, self.parent, bg='bisque', borderwidth=1, relief="sunken")
self.__create_layout()
def __create_layout(self):
self.frame1 = tk.Frame(self, bg="yellow")
self.frame2 = tk.Frame(self, bg="blue")
self.frame3 = LeftMiddle(self) # tk.Frame(self, bg="green")
self.frame4 = tk.Frame(self, bg="brown")
self.frame5 = tk.Frame(self, bg="pink")
self.frame1.grid(row=0, column=0, rowspan=4, columnspan=8, sticky=(tk.N, tk.S, tk.W, tk.E))
self.frame2.grid(row=0, column=8, rowspan=4, columnspan=2, sticky=(tk.N, tk.S, tk.W, tk.E))
self.frame3.grid(row=4, column=0, rowspan=2, columnspan=5, sticky=(tk.N, tk.S, tk.W, tk.E))
self.frame4.grid(row=4, column=5, rowspan=2, columnspan=5, sticky=(tk.N, tk.S, tk.W, tk.E))
self.frame5.grid(row=5, column=0, rowspan=1, columnspan=10, sticky=(tk.N, tk.S, tk.W, tk.E))
for r in range(6):
self.rowconfigure(r, weight=1)
for c in range(10):
self.columnconfigure(c, weight=1)
#
# MAIN
#
def main():
root = tk.Tk()
root.title("Frames")
root.geometry("550x300+525+300")
root.configure(background="#808080")
root.option_add("*font", ("Courier New", 9, "normal"))
window = MainWindow(master=root)
window.pack(side="top", fill="both", expand=True)
root.mainloop()
if __name__ == '__main__':
main()
You have overlapping frames. Both self.frame3 and self.frame4 are in row 4 with a rowspan of 2, meaning they occupy rows 4 and 5. self.frame5 is also in row 5. So, self.frame5 is obscuring the bottom half of self.frame3, the frame that contains the canvas.
I don't understand why you have so many rowspans, they seem completely unnecessary unless you have some specific reason why you want multiple rows and columns but only single frames that span these rows and columns. Looking at the screenshot I see the need for only three rows.
The reason the text seems off is that by default the text is centered over the coordinate you give. You might want to look at the anchor option for the create_text method.

Scrolling and correct scaling with Tkinter

I need this simple form to:
1) correctly expand the fields when the window size is adjusted and
2) correctly scroll the list of fields.
I've tried every way I can think of and only 1 of the 2 above conditions are ever true. This code expands properly but does not scroll. Without frame2, and adding the fields to frame or canvas the opposite is true.
class test(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def makeform(self, root, fields):
i = 0
for field in fields:
Label(root, text=field + ": ", anchor=W).grid(row=i)
entry = Entry(root)
entry.grid(row=i, column=1, sticky=E+W)
entries[field] = entry
i += 1
def initialize(self):
frame = Frame(self)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
frame.grid(sticky=N+S+E+W)
canvas = Canvas(frame, width=900, height=800, bg='pink')
canvas.grid(row=0, column=0, sticky=N+S+E+W)
canvas.columnconfigure(0,weight=1)
canvas.rowconfigure(0,weight=1)
frame2 = Frame(canvas)
frame2.grid(row=0, column=0, sticky=N+S+E+W)
frame2.columnconfigure(1, weight=1)
vscrollbar = Scrollbar(frame2,orient=VERTICAL)
vscrollbar.grid(row=0, column=2, sticky=N+S)
vscrollbar.config(command=canvas.yview)
canvas.configure(yscrollcommand=vscrollbar.set)
self.grid_rowconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
names = {'a','long','list','of','names','here'}
self.makeform(frame2, names)
Button(self, text='Quit', command=self.quit).grid(row=1, column=0, sticky=W, pady=4)
canvas.create_window(0, 0)
canvas.config(scrollregion=canvas.bbox(ALL))
self.grid()
if __name__ == "__main__":
entries = {}
app = test(None)
app.title('Hi ')
app.mainloop()
Update
Integrating Bryan's example below, this works for scrolling but does not expand the fields when the window is resized. I tried adding weight=1 to the second column of the frame but it does not help. How do I prevent the frame from shrinking?
class test(Tkinter.Frame):
def __init__(self,parent):
Tkinter.Frame.__init__(self, root)
self.canvas = Tkinter.Canvas(root, borderwidth=0, background="#ffffff")
self.frame = Tkinter.Frame(self.canvas, background="#ffffff")
self.vsb = Tkinter.Scrollbar(root, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((0,0), window=self.frame, anchor="nw",
tags="self.frame")
self.frame.bind("<Configure>", self.onFrameConfigure)
self.populate()
def onFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def makeform(self, fields):
i = 0
for field in fields:
Label(self.frame, text=field + ": ", anchor=W).grid(row=i)
entry = Entry(self.frame)
entry.grid(row=i, column=1, sticky=E+W)
entries[field] = entry
i += 1
Button(self.frame, text='Quit', command=self.quit).grid(row=i, column=0, sticky=W, pady=4)
def populate(self):
names = {'a','long','list','of','names','here'}
self.makeform(names)
self.frame.columnconfigure(1, weight=1)
self.frame.grid_columnconfigure(1, weight=1)
if __name__ == "__main__":
entries = {}
root=Tk()
test(root).pack(side="top", fill="both", expand=True)
root.mainloop()
There are at least three problems in your code.
First, the frame to be scrolled must be a part of the canvas. You can't use pack or grid to place it in the canvas, you must use create_window. You're calling create_window but you aren't telling it what window to add.
Second, the scrollbars are children of the frame, but I'm assuming those are the scrollbars you want to scroll the canvas. The need to be outside of the inner frame, and outside of the canvas.
Third, you need to set up a binding to the canvas's <Configure> event so that you can resize the inner frame and recompute the scrollregion of the canvas.
A complete working example of a scrollable frame is in this answer: https://stackoverflow.com/a/3092341/7432

Categories

Resources