尝试使用ttk时。滚动条功能,即使expand=True,我的框架也不会展开以填充画布。我在其他帖子中也发现了类似的问题,但他们使用的解决方案并没有解决我的问题。
下面是我的代码的简化版本,以显示这个问题。我基本上想要粉红色的区域来填充整个画布。
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)
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")
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()
这里有几点需要注意:
-
除非被告知不要(使用
pack_propagate(0)
并需要在尺寸上让步),否则self.canvas_id
只会增长其子代所需的空间 -
您在主窗口上手动设置维度,这反过来会使
self.canvas
增长以填充该维度,因为您在self.canvas
上使用pack(side="left", expand=1, fill="both")
。 -
即使使用expand=True ,我的框架也不会展开以填充画布
您的帧
self.container
不会扩展self.canvas
的整个大小,因为它只能增长与其父帧(self.canvas_id
)一样多,除非被告知这样做,否则父帧也不会增长与画布一样多。此外,由于self.canvas_id
在画布内是一个window
,您无法使它像预期的那样与pack
一起增长,每次画布更改大小时,您都必须启动一个事件,并更改帧大小以匹配画布的大小。 -
现在,当您使用
pack_propagate(0)
时会出现另一个问题,这使得设置self.container
的height
以使帧超过画布的当前大小成为一个问题(只有这样滚动才能正常工作)。为了解决这个问题,我们将在self.canvas
上配置其大小,而不是使用pack_propagate(0)
并直接更改self.canvas_id
的大小。
self.canvas.create_window((0,0), window=self.canvas_id, anchor="nw", tags='window') # Add a tag
self.canvas.bind('<Configure>', lambda e: self.canvas.itemconfig('window', width=e.width)) # Use that tag to identify that window and change the size
这种解释有点假设你什么都不知道,所以它包含了一些看起来很难理解的概念。