I am using the following code for having a scrollable frame. I want now each column in the grid to fill the whole window horizontally, also when the window size changes.
For this approach I have always used frame.grid_columnconfigure(col_num, weight=1) and added the sticky="ew" parameter to the .grid(row, col) command when placing an element.
For some reason (maybe has to do with the canvas window) this approach does not work in the following code.
import tkinter as tk
# ************************
# Scrollable Frame Class
# ************************
class ScrollFrame(tk.Frame):
def __init__(self, parent):
super().__init__(parent) # create a frame (self)
# place canvas on self
self.canvas = tk.Canvas(self, borderwidth=0, background="#ffffff")
# place a frame on the canvas, this frame will hold the child widgets
self.viewPort = tk.Frame(self.canvas, background="#ffffff")
# place a scrollbar on self
self.vsb = tk.Scrollbar(self, orient="vertical",
command=self.canvas.yview)
# attach scrollbar action to scroll of canvas
self.canvas.configure(yscrollcommand=self.vsb.set)
# pack scrollbar to right of self
self.vsb.pack(side="right", fill="y")
# pack canvas to left of self and expand to fil
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((4, 4), window=self.viewPort, anchor="nw", # add view port frame to canvas
tags="self.viewPort")
# bind an event whenever the size of the viewPort frame changes.
self.viewPort.bind("<Configure>", self.onFrameConfigure)
def onFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox(
"all")) # whenever the size of the frame changes, alter the scroll region respectively.
# ********************************
# Example usage of the above class
# ********************************
class Example(tk.Frame):
def __init__(self, root):
tk.Frame.__init__(self, root)
self.scrollFrame = ScrollFrame(self) # add a new scrollable frame.
# try to make the columns filling the entire frame
self.scrollFrame.viewPort.grid_columnconfigure(0, weight=1)
self.scrollFrame.viewPort.grid_columnconfigure(1, weight=1)
# Now add some controls to the scrollframe.
# NOTE: the child controls are added to the view port (scrollFrame.viewPort, NOT scrollframe itself)
for row in range(100):
a = row
tk.Label(self.scrollFrame.viewPort, text="%s" % row, width=3, borderwidth="1",
relief="solid").grid(row=row, column=0, sticky="ew")
t = "this is the second column for row %s" % row
tk.Button(self.scrollFrame.viewPort, text=t, command=lambda x=a: self.printMsg(
"Hello " + str(x))).grid(row=row, column=1, sticky="ew")
# when packing the scrollframe, we pack scrollFrame itself (NOT the viewPort)
self.scrollFrame.pack(side="top", fill="both", expand=True)
def printMsg(self, msg):
print(msg)
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Many thanks beforehand for any suggestions!