Search code examples
pythontkinterframe

How to horizontally center all the elements in a scrollable frame using pack and grid layout


I was trying to learn how to make frame scrollable. Now i got another problem how to center all the widgets horizontally in that frame. The labels, the buttons all appear on the left. How can I center them horizontally.

import tkinter as tk
from tkinter import ttk

root = tk.Tk()

container = tk.Frame(root)
container.pack(fill="both", expand=True)

canvas = tk.Canvas(container)
canvas.pack(side="left", fill="both", expand=True)

scrollbar = ttk.Scrollbar(container, orient="vertical", command=canvas.yview)
scrollbar.pack(side="right", fill="y")

canvas.configure(yscrollcommand=scrollbar.set)

scrollable_frame = ttk.Frame(canvas)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")

scrollable_frame.bind(
    "<Configure>",
    lambda e: canvas.configure(
        scrollregion=canvas.bbox("all")
    )
)

for i in range(50):
    tk.Label(scrollable_frame, text="Sample text").grid(row=i, column=0)
    tk.Button(scrollable_frame, text="Sample text").grid(row=i, column=1)

root.mainloop()

Solution

  • You can calculate the required position of the top-left corner of scrollable_frame and move the frame using canvas.coords() whenever the canvas is resized:

    frame_id = canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
    
    def on_canvas_resize(event):
        x = (event.width - scrollable_frame.winfo_width()) / 2
        canvas.coords(frame_id, (x, 0))
        bbox = (0, 0, event.width, scrollable_frame.winfo_height())
        canvas.config(scrollregion=bbox)
    
    canvas.bind("<Configure>", on_canvas_resize)