gpt4 book ai didi

python - 为什么 place() 不适用于 Canvas 中框架中的小部件?

转载 作者:太空狗 更新时间:2023-10-30 02:44:04 25 4
gpt4 key购买 nike

我正在尝试创建一个可以包含其他小部件的可滚动 Python Tkinter 小部件。下面的伪代码(主要是从 this SO question 的答案中提取出来的,然后根据我的风格进行了调整)似乎几乎完全符合我的要求:

import Tkinter as tk

class ScrollFrame(tk.Frame):
def __init__(self, root, *args, **kwargs):
# Start up self
tk.Frame.__init__(self, root, *args, **kwargs)
# Put a canvas in the frame (self), along with scroll bars
self.canvas = tk.Canvas(self)
self.horizontal_scrollbar = tk.Scrollbar(
self, orient="horizontal", command=self.canvas.xview
)
self.vertical_scrollbar = tk.Scrollbar(
self, orient="vertical", command=self.canvas.yview
)
self.canvas.configure(
yscrollcommand=self.vertical_scrollbar.set,
xscrollcommand=self.horizontal_scrollbar.set
)
# Put a frame in the canvas, to hold all the widgets
self.inner_frame = tk.Frame(self.canvas)
# Pack the scroll bars and the canvas (in self)
self.horizontal_scrollbar.pack(side="bottom", fill="x")
self.vertical_scrollbar.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((0,0), window=self.inner_frame, anchor="nw")
self.inner_frame.bind("<Configure>", self.OnFrameConfigure)

def OnFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox("all"))

root = tk.Tk()
frame = ScrollFrame(root, borderwidth=2, relief="sunken")
labels = []
for i in range(10):
labels.append(
tk.Label(
frame.inner_frame, text="Row {}".format(i) + "_"*20
) # Unfortunately, this widget's parent cannot just be frame but has to be frame.inner_frame
)
frame.place(x=20, y=20, width=150, height=150)

for i,label in enumerate(labels):
label.grid(row=i,column=0)
#label.place(x=0, y=20*i, width=100, height=20)
root.mainloop()

(有10个标签,每个标签最后都有一些垃圾信息,测试垂直和水平滚动是否都有效。)

但是,对于我的实际应用程序,我需要非常精细地控制每个小部件的最终位置,这迫使我使用 place 几何管理器而不是 grid。 (请注意,我 place()d 框架。)但是,如果我用 place( ),标签不再显示。 (在上面的代码中,通过注释掉倒数第三行并取消注释倒数第二行来模拟这一点。)

为什么这行不通?我该如何解决?


编辑:通过将 inner_widthinner_height 传递给 ScrollFrame 类的初始化,接受的答案使我得到了以下代码,该代码按预期工作,然后作为 inner_framewidthheight 参数传递:

import Tkinter as tk

class ScrollFrame(tk.Frame):
def __init__(self, root, inner_width, inner_height, *args, **kwargs):
# Start up self
tk.Frame.__init__(self, root, *args, **kwargs)
# Put a canvas in the frame (self)
self.canvas = tk.Canvas(self)
# Put scrollbars in the frame (self)
self.horizontal_scrollbar = tk.Scrollbar(
self, orient="horizontal", command=self.canvas.xview
)
self.vertical_scrollbar = tk.Scrollbar(
self, orient="vertical", command=self.canvas.yview
)
self.canvas.configure(
yscrollcommand=self.vertical_scrollbar.set,
xscrollcommand=self.horizontal_scrollbar.set
)
# Put a frame in the canvas, to hold all the widgets
self.inner_frame = tk.Frame(
self.canvas, width=inner_width, height=inner_height
)
# Pack the scroll bars and the canvas (in self)
self.horizontal_scrollbar.pack(side="bottom", fill="x")
self.vertical_scrollbar.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((0,0), window=self.inner_frame, anchor="nw")
self.inner_frame.bind("<Configure>", self.on_frame_configure)

def on_frame_configure(self, event):
"""Reset the scroll region to encompass the inner frame"""
self.canvas.configure(scrollregion=self.canvas.bbox("all"))


root = tk.Tk()
frame = ScrollFrame(root, 150, 200, borderwidth=2, relief="sunken")
labels = []
for i in range(10):
labels.append(
tk.Label(
frame.inner_frame, text="Row {}".format(i) + "_"*20, anchor="nw"
) # Unfortunately, this widget's parent cannot just be frame but has to be frame.inner_frame
)
frame.place(x=20, y=20, width=150, height=150)

for i,label in enumerate(labels):
#label.grid(row=i,column=0)
label.place(x=0, y=20*i, width=100, height=20)
root.mainloop()

最佳答案

这是因为 place 不会调整父窗口的大小来容纳子窗口部件。使用 place 时需要明确设置父框架的大小。您的标签在那里,但框架的默认大小为 1x1 像素,有效地使标签不可见。

来自official documentation for place :

Unlike many other geometry managers (such as the packer) the placer does not make any attempt to manipulate the geometry of the master windows or the parents of slave windows (i.e. it does not set their requested sizes). To control the sizes of these windows, make them windows like frames and canvases that provide configuration options for this purpose.

如果你需要做的只是在一个可滚动的 Canvas 上以绝对控制管理一堆小部件,只需使用 Canvas 方法create_window,它可以让你将标签直接放在 Canvas 上的精确坐标处.这比使用 place 将小部件放入框架中,然后将框架放入 Canvas 中要容易得多。

关于python - 为什么 place() 不适用于 Canvas 中框架中的小部件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31028874/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com