使用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() # 补充主循环,原代码遗漏此部分
关键说明
- 新增
self.canvas.bind("<Configure>", self.on_canvas_configure)监听Canvas的尺寸变化,当Canvas宽度改变时触发回调 - 在
on_canvas_configure方法中,将canvas_id的宽度设置为Canvas当前宽度,确保内部的InnerFrame能通过fill="both"和expand=1填满Canvas宽度 - 补充
a.mainloop()保证窗口正常运行
内容的提问来源于stack exchange,提问作者sophrosyne
相关产品推荐
相关产品推荐

