这与之前的问题有关: Tkinter dynamically create widgets from button
在我问上一个问题时,我相信在动态GUI周围添加可滚动框架会很容易。相反,我遇到一个问题,滚动条在按下按钮后没有检测到新的帧和输入框。如何在不编辑ScrollFrame类的情况下解决这个问题呢?
我知道Scrollbarframe与其他小部件一起工作只是动态组件导致问题。当我缩小窗口的垂直大小超过createWidgets按钮的原始位置时,会出现滚动条,但其余动态创建的小部件不会显示滚动条。画布是否通过按下按钮检测到框架的垂直尺寸是否增加?
注意:我知道通配符导入很糟糕。我只是用一个例子
from tkinter import *
class AutoScrollbar(Scrollbar):
# A scrollbar that hides itself if it's not needed.
# Only works if you use the grid geometry manager!
def set(self, lo, hi):
if float(lo) <= 0.0 and float(hi) >= 1.0:
# grid_remove is currently missing from Tkinter!
self.tk.call("grid", "remove", self)
else:
self.grid()
Scrollbar.set(self, lo, hi)
def pack(self, **kw):
raise TclError("cannot use pack with this widget")
def place(self, **kw):
raise TclError("cannot use place with this widget")
class ScrollFrame:
def __init__(self, master):
self.vscrollbar = AutoScrollbar(master)
self.vscrollbar.grid(row=0, column=1, sticky=N+S)
self.hscrollbar = AutoScrollbar(master, orient=HORIZONTAL)
self.hscrollbar.grid(row=1, column=0, sticky=E+W)
self.canvas = Canvas(master, yscrollcommand=self.vscrollbar.set,
xscrollcommand=self.hscrollbar.set)
self.canvas.grid(row=0, column=0, sticky=N+S+E+W)
self.vscrollbar.config(command=self.canvas.yview)
self.hscrollbar.config(command=self.canvas.xview)
# make the canvas expandable
master.grid_rowconfigure(0, weight=1)
master.grid_columnconfigure(0, weight=1)
# create frame inside canvas
self.frame = Frame(self.canvas)
self.frame.rowconfigure(1, weight=1)
self.frame.columnconfigure(1, weight=1)
def update(self):
self.canvas.create_window(0, 0, anchor=NW, window=self.frame)
self.frame.update_idletasks()
self.canvas.config(scrollregion=self.canvas.bbox("all"))
if self.frame.winfo_reqwidth() != self.canvas.winfo_width():
# update the canvas's width to fit the inner frame
self.canvas.config(width = self.frame.winfo_reqwidth())
if self.frame.winfo_reqheight() != self.canvas.winfo_height():
# update the canvas's width to fit the inner frame
self.canvas.config(height = self.frame.winfo_reqheight())
frames = []
widgets = []
def createwidgets():
global widgetNames
global frameNames
frame = Frame(o.frame, borderwidth=2, relief="groove")
frames.append(frame)
frame.pack(side="top", fill="x")
widget = Entry(frame)
widgets.append(widget)
widget.pack(side="left")
root = Tk()
o = ScrollFrame(root)
label = Label(o.frame, text = "test")
label1 = Label(o.frame, text = "test")
label2 = Label(o.frame, text = "test")
label3 = Label(o.frame, text = "test")
label.pack()
label1.pack()
label2.pack()
label3.pack()
createWidgetButton = Button(o.frame, text="createWidgets",
command=createwidgets)
createWidgetButton.pack(side="bottom", fill="x")
o.update()
root.mainloop()
如果窗口完全展开,这就是窗口的样子
如果我要缩小窗口,它应该立即创建一个垂直滚动条,因为它会覆盖一个小部件。但是,滚动条就像程序仍处于初始状态一样。
滚动条不正确(滚动条出现时)
答案 0 :(得分:3)
每当您向内部框架添加小部件时,都需要确保更新画布scrollregion
。最常见的解决方案是绑定到框架的<Configure>
事件,只要框架改变大小,该事件就会触发。
在ScrollFrame.__init__
中,在创建框架后添加以下行:
self.frame.bind("<Configure>", self.reset_scrollregion)
然后,将此功能添加到ScrollFrame
:
def reset_scrollregion(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all")