使用滚动条时,画布内的 tkinter 框架不会扩展



尝试使用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()

这里有几点需要注意:

  1. 除非被告知不要(使用pack_propagate(0)并需要在尺寸上让步),否则self.canvas_id只会增长其子代所需的空间

  2. 您在主窗口上手动设置维度,这反过来会使self.canvas增长以填充该维度,因为您在self.canvas上使用pack(side="left", expand=1, fill="both")

  3. 即使使用expand=True ,我的框架也不会展开以填充画布

    您的帧self.container不会扩展self.canvas的整个大小,因为它只能增长与其父帧(self.canvas_id)一样多,除非被告知这样做,否则父帧也不会增长与画布一样多。此外,由于self.canvas_id在画布内是一个window,您无法使它像预期的那样与pack一起增长,每次画布更改大小时,您都必须启动一个事件,并更改帧大小以匹配画布的大小。

  4. 现在,当您使用pack_propagate(0)时会出现另一个问题,这使得设置self.containerheight以使帧超过画布的当前大小成为一个问题(只有这样滚动才能正常工作)。为了解决这个问题,我们将在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

这种解释有点假设你什么都不知道,所以它包含了一些看起来很难理解的概念。

最新更新