You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Scrollbar时Tkinter Canvas内Frame无法扩展填充问题

解决Canvas内部Frame无法填充整个Canvas的问题

问题核心在于:通过canvas.create_window添加到Canvas的Frame不会自动跟随Canvas的宽度变化而调整尺寸。要让粉色区域(InnerFrame)填满Canvas,需要监听Canvas的尺寸变化,同步更新内部Frame的宽度。

修改方案

在OuterFrame类中新增Canvas的尺寸监听事件,同步调整内部Frame的宽度:

import tkinter as tk
from tkinter import ttk


class MyView(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Any help is appreciated :)")
        self.geometry("600x300")

        self.container = OuterFrame(self)
        self.container.pack(expand=1, fill="both")


class OuterFrame(tk.Frame):
    def __init__(self, container):
        super().__init__(container)

        # CONTAINERS
        self.canvas = tk.Canvas(self)
        self.canvas.pack(side="left", expand=1, fill="both")

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

        self.canvas.config(yscrollcommand=self.scrollbar.set)

        self.canvas_id = tk.Frame(self.canvas)
        # 绑定Canvas尺寸变化事件,同步更新内部Frame宽度
        self.canvas.bind("<Configure>", self.on_canvas_configure)
        self.canvas_id.bind("<Configure>", lambda e: self.canvas.config(scrollregion=self.canvas.bbox("all")))
        self.canvas.create_window((0, 0), window=self.canvas_id, anchor="nw")

        self.container = InnerFrame(self.canvas_id)
        self.container.pack(expand=1, fill="both")

    def on_canvas_configure(self, event):
        # 将内部Frame的宽度设置为Canvas当前宽度
        self.canvas_id.config(width=event.width)


class InnerFrame(tk.Frame):
    def __init__(self, container):
        super().__init__(container)
        self.config(bg="pink")

        self.titles = ["test1", "test2", "test3", "test4", "test5", "test6"]

        self.label = tk.Label(self, text="Objectives")
        self.label.pack(pady=5)

        self.checkvars = {}  # for the ckeckbuttons
        self.frames = {}

        for title in self.titles:
            self.checkvars[title] = tk.IntVar()
            self.frames[title] = InnerFrameObjective(self, title, self.checkvars[title])
            self.frames[title].pack(expand=1, fill="x", pady=(0, 15))


class InnerFrameObjective(tk.Frame):
    def __init__(self, container, string, checkvar):
        super().__init__(container)
        self.configure(pady=4, padx=30, bg="pink")
        self.title = string

        self.Framelabels = InnerFrameObjectiveLabels(self)
        self.Framelabels.pack(side="left", expand=1, fill="both")

        self.checkbutton = tk.Checkbutton(self, variable=checkvar, onvalue=1, offvalue=0, bg="blue")
        self.checkbutton.pack(side="right", expand=1, fill="both")


class InnerFrameObjectiveLabels(tk.Frame):
    def __init__(self, container):
        super().__init__(container)
        self.parent = container
        self.config(bg="blue")

        self.title = self.parent.title
        self.due_date = None

        self.label = tk.Label(self, text=self.title, bg="blue")
        self.label.pack()

        self.label2 = tk.Label(self, text="Due Date:", bg="blue")
        self.label2.pack(anchor="w")


a = MyView()
a.mainloop()  # 补充主循环,原代码遗漏此部分

关键说明

  1. 新增self.canvas.bind("<Configure>", self.on_canvas_configure)监听Canvas的尺寸变化,当Canvas宽度改变时触发回调
  2. 在on_canvas_configure方法中,将canvas_id的宽度设置为Canvas当前宽度,确保内部的InnerFrame能通过fill="both"和expand=1填满Canvas宽度
  3. 补充a.mainloop()保证窗口正常运行

内容的提问来源于stack exchange,提问作者sophrosyne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 02:10:20