Module_art
Module_art

Reputation: 1068

How to resize Canvas scrollable widget?

The idea is that the scrollable canvas and its text widgets grow or fill the entire root/toplevel when I resize it.

I can do this if I work on Frames but for a scrollable frame you need to create a canvas widget and make it scrollable. Now I don't know if the problem is the canvas or the inserted widgets on the canvas?

import tkinter as tk
from tkinter import ttk

class ScrollableFrame():
    def __init__(self, container, *args, **kwargs):
        self.container = container
        self.canvas = tk.Canvas(self.container, bg="green")
        self.scrollbar = ttk.Scrollbar(self.container, orient="horizontal", command=self.canvas.xview)
        self.scrollable_frame = tk.Frame(self.canvas)
        self.scrollable_frame.grid(sticky="wesn")
        self.scrollable_frame.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))

        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
        self.canvas.configure(xscrollcommand=self.scrollbar.set)
        
        self.canvas.grid(row=0, column=0, sticky="wesn")
        self.scrollbar.grid(row=1, column=0, sticky="wesn")
        
if __name__ == "__main__":
    root = tk.Tk()
    root.configure(bg="grey20")
    
    s = ScrollableFrame(root)
    
    t = tk.Text(s.scrollable_frame)
    t.grid(row=0, column=0, sticky="wesn")
    
    t2 = tk.Text(s.scrollable_frame)
    t2.grid(row=0, column=1, sticky="wesn")

    root.mainloop()
    

I'm glad for help

Upvotes: 3

Views: 165

Answers (1)

acw1668
acw1668

Reputation: 46678

Base on the requirement in the comment, you want to grow/shrink the two text boxes when the root window is resized. Below is the modified code with the necessary changes to achieve it:

import tkinter as tk
from tkinter import ttk

class ScrollableFrame():
    def __init__(self, container, *args, **kwargs):
        self.container = container
        self.canvas = tk.Canvas(self.container, bg="green")
        self.scrollbar = ttk.Scrollbar(self.container, orient="horizontal", command=self.canvas.xview)
        self.scrollable_frame = tk.Frame(self.canvas)
        self.scrollable_frame.grid(sticky="wesn")
        self.scrollable_frame.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))

        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw", tags="scrollable")
        self.canvas.configure(xscrollcommand=self.scrollbar.set)

        self.canvas.grid(row=0, column=0, sticky="wesn")
        self.scrollbar.grid(row=1, column=0, sticky="we") # fill horizontally only

        # make self.canvas to fill all the available space of container
        container.rowconfigure(0, weight=1)
        container.columnconfigure(0, weight=1)

        # resize self.scrollable_frame when self.canvas is resized
        self.canvas.bind("<Configure>", lambda e: self.canvas.itemconfig("scrollable", width=e.width, height=e.height))

if __name__ == "__main__":
    root = tk.Tk()
    root.configure(bg="grey20")

    s = ScrollableFrame(root)

    # make the two text boxes to fill all the space of s.scrollable_frame
    s.scrollable_frame.rowconfigure(0, weight=1)
    s.scrollable_frame.columnconfigure((0,1), weight=1)

    t = tk.Text(s.scrollable_frame)
    t.grid(row=0, column=0, sticky="wesn")

    t2 = tk.Text(s.scrollable_frame)
    t2.grid(row=0, column=1, sticky="wesn")

    root.mainloop()

So basically the logic is when the root window is resized, the canvas is resized to fill the root window. Then the frame (scrollable_frame) inside the canvas is resized to fill the canvas and finally the two text widgets are resized to fill the scrollable_frame.

Upvotes: 2

Related Questions