这与上一个问题有关: Tkinter dynamic 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()
Run Code Online (Sandbox Code Playgroud)
这是窗口完全展开后的样子

如果我要缩小窗口,它应该立即创建一个垂直滚动条,因为它会覆盖一个小部件。但是,滚动条就像程序仍处于初始状态一样。
不正确的滚动条(在滚动条出现的那一刻)

scrollregion每当您将小部件添加到内部框架时,您都需要确保更新画布。最常见的解决方案是绑定到框架的<Configure>事件,该事件将在框架改变大小时触发。
在ScrollFrame.__init__创建框架后添加以下行:
self.frame.bind("<Configure>", self.reset_scrollregion)
Run Code Online (Sandbox Code Playgroud)
然后,将此函数添加到ScrollFrame:
def reset_scrollregion(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3270 次 |
| 最近记录: |