How it works…

The first lines of our application create the scroll bars and connect them to the Canvas object with the xscrollcommand and yscrollcommand options, which take a reference to the set() method of scroll_x and scroll_y, respectively—this is the method in charge of moving the scroll bar slider.

It is also necessary to configure the command option of each scroll bar once the Canvas is defined:

self.scroll_x = tk.Scrollbar(self, orient=tk.HORIZONTAL)
self.scroll_y = tk.Scrollbar(self, orient=tk.VERTICAL)
self.canvas = tk.Canvas(self, width=300, height=100,
xscrollcommand=self.scroll_x.set,
yscrollcommand=self.scroll_y.set)
self.scroll_x.config(command=self.canvas.xview)
self.scroll_y.config(command=self.canvas.yview)

It is also possible to create the Canvas first and configure its options later, when the scroll bars are instantiated.

The next step is to add the frame to our scrollable Canvas with the create_window() method. The first argument it takes is the position to place the widget passed with the window option. Since the x and y axes of the Canvas widget start in the top-left corner, we placed the frame at the (0, 0) position and also aligned it to that corner with anchor=tk.NW (north-west):

self.frame = tk.Frame(self.canvas)
# ...
self.canvas.create_window((0, 0), window=self.frame, anchor=tk.NW)

Then, we will make the first row and column resizable with the rowconfigure() and columnconfigure() methods. The weight option indicates the relative weight to distribute the extra space, but in our case, there are no more rows or columns to resize.

The binding to the <Configure> event will help us to properly reconfigure the canvas when the main window gets resized. Handling this type of event follows the same principles that we saw in the previous chapter to process mouse and keyboard events:

self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
self.bind("<Configure>", self.resize)

Finally, we will set the minimum size of the main window with the current width and height, which can be retrieved with the winfo_width() and winfo_height() methods.

In order to get the real size of a container, we have to force the geometry manager to draw all the child widgets first by calling update_idletasks(). This method is available in all widget classes, and forces Tkinter to process all pending idle events, such as redrawings and geometry recalculations:

self.update_idletasks()
self.minsize(self.winfo_width(), self.winfo_height())

The resize method handles the window resize event and updates the scrollregion option, which defines the area of the canvas that can be scrolled. To easily recalculate it, you can use the bbox() method with the ALL constant. This returns the bounding box of the whole Canvas widget:

def resize(self, event):
region = self.canvas.bbox(tk.ALL)
self.canvas.configure(scrollregion=region)

Tkinter will automatically trigger several <Configure>­ events when we start our application, so there is no need to call self.resize() at the end of the __init__ method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset