I adapted the solution by Bryan Oakley at Adding a scrollbar to a group of widgets in Tkinter to implement a scrollbar on a tkinter Frame. (The code reads key/value pairs from a dict and generates a series of editable entries in table format, prefaced by a checkbox that enables the user to delete entries.) I can get his code working but not my own: the scrollbar is present but does not become enabled. The background colors suggest that the canvas is expanding just as the frame is, which would explain why no working scrollbar, but I don't know why the canvas expands. Any suggestions? Thanks.
def make_table(map, widget, prefix):
delete_label_str = StringVar()
delete_label_str.set('Delete')
delete_label = tk.Label(widget, textvariable=delete_label_str, width=6, height=1, justify=tk.CENTER)
delete_label.grid(row=0, column=0)
abbrev_label_str = StringVar()
abbrev_label_str.set('Name')
abbrev_label = tk.Label(widget, textvariable=abbrev_label_str, height=1, width=6, justify=tk.CENTER)
abbrev_label.grid(row=0, column=1)
def_label_str = StringVar()
def_label_str.set('Definition')
def_label = tk.Label(widget, textvariable=def_label_str, height=1, width=45, justify=tk.LEFT)
def_label.grid(row=0, column=2)
if not map or len(map) == 0:
return
row_num = 1
for key in map.keys():
delete_var_name = prefix + str(row_num)
globals()[delete_var_name] = BooleanVar()
globals()[delete_var_name].set(False)
delete_checkbox = tk.Checkbutton(widget, variable=globals()[delete_var_name], height=1, anchor=tk.W)
delete_checkbox.grid(row=row_num, column=0)
e1 = tk.Entry(widget, width=6, )
e1.grid(row=row_num, column=1)
e1.insert(END, key)
e2 = tk.Entry(widget, width=45, )
e2.grid(row=row_num, column=2)
e2.insert(END, map[key])
row_num+=1
def onFrameConfigure(canvas):
#Reset the scroll region to encompass the inner frame
canvas.configure(scrollregion=canvas.bbox("all"))
def show_abbrevs():
dlog = tk.Toplevel(root)
dlog.title('Abbreviations')
dlog.geometry('425x325')
delete_prefix = 'delete_abbr_value'
global cur_path
if cur_path:
basepath = os.path.splitext(cur_path)[0]
fname = basepath + '.abb'
else:
fname = my_path + '/picardy.abb'
canvas = tk.Canvas(dlog, borderwidth=0, background="blue")
table_frame = tk.Frame(canvas, pady=10, padx=5, background="yellow")
vsb = tk.Scrollbar(dlog, orient="vertical", command=canvas.yview, )
canvas.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
canvas.pack(side="top", fill="both", expand=True)
canvas.create_window((4,4), window=table_frame, anchor="nw")
table_frame.bind("<Configure>", lambda event, canvas=canvas:onFrameConfigure(canvas))
table_frame.pack()
#table_frame.focus_set()
make_table(abbrev_map, table_frame, delete_prefix)
button_frame = tk.Frame(dlog, pady=10)
new = tk.Button(button_frame, text="Add", width=10, height=1, command=lambda:add_entry(table_frame, delete_prefix))
new.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
delete = tk.Button(button_frame, text="Delete", width=10, height=1, command=lambda:delete_entries(table_frame, delete_prefix))
delete.grid(row=0, column=1, sticky="ew", padx=5, pady=5)
save = tk.Button(button_frame, text="Save", width=10, height=1, command=lambda:save_entries(table_frame, fname, delete_prefix))
save.grid(row=0, column=2, sticky="ew", padx=5, pady=5)
button_frame.pack()
I used your code in simple example and worked when used
scrollregion
arugment in canvasi was creating small dynamic helper functions to create grid with unlimited rows and max 3 cols you can test the scroll in this example full code and grid Drawer function
https://github.com/MahmoudHegazi/tkinter_grid_lib