使用 Tkinter 滚动和正确缩放
Scrolling and correct scaling with Tkinter
我需要这个简单的表格来:
1) 调整 window 大小时正确扩展字段和
2) 正确滚动字段列表。
我已经尝试了所有我能想到的方法,但上述 2 个条件中只有 1 个是正确的。此代码可以正确展开但不会滚动。没有 frame2,并将字段添加到 frame 或 canvas 则相反。
class test(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def makeform(self, root, fields):
i = 0
for field in fields:
Label(root, text=field + ": ", anchor=W).grid(row=i)
entry = Entry(root)
entry.grid(row=i, column=1, sticky=E+W)
entries[field] = entry
i += 1
def initialize(self):
frame = Frame(self)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
frame.grid(sticky=N+S+E+W)
canvas = Canvas(frame, width=900, height=800, bg='pink')
canvas.grid(row=0, column=0, sticky=N+S+E+W)
canvas.columnconfigure(0,weight=1)
canvas.rowconfigure(0,weight=1)
frame2 = Frame(canvas)
frame2.grid(row=0, column=0, sticky=N+S+E+W)
frame2.columnconfigure(1, weight=1)
vscrollbar = Scrollbar(frame2,orient=VERTICAL)
vscrollbar.grid(row=0, column=2, sticky=N+S)
vscrollbar.config(command=canvas.yview)
canvas.configure(yscrollcommand=vscrollbar.set)
self.grid_rowconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
names = {'a','long','list','of','names','here'}
self.makeform(frame2, names)
Button(self, text='Quit', command=self.quit).grid(row=1, column=0, sticky=W, pady=4)
canvas.create_window(0, 0)
canvas.config(scrollregion=canvas.bbox(ALL))
self.grid()
if __name__ == "__main__":
entries = {}
app = test(None)
app.title('Hi ')
app.mainloop()
更新
整合下面的 Bryan 示例,这适用于滚动,但在 window 调整大小时不会扩展字段。我尝试将 weight=1 添加到框架的第二列,但没有帮助。如何防止边框缩小?
class test(Tkinter.Frame):
def __init__(self,parent):
Tkinter.Frame.__init__(self, root)
self.canvas = Tkinter.Canvas(root, borderwidth=0, background="#ffffff")
self.frame = Tkinter.Frame(self.canvas, background="#ffffff")
self.vsb = Tkinter.Scrollbar(root, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((0,0), window=self.frame, anchor="nw",
tags="self.frame")
self.frame.bind("<Configure>", self.onFrameConfigure)
self.populate()
def onFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def makeform(self, fields):
i = 0
for field in fields:
Label(self.frame, text=field + ": ", anchor=W).grid(row=i)
entry = Entry(self.frame)
entry.grid(row=i, column=1, sticky=E+W)
entries[field] = entry
i += 1
Button(self.frame, text='Quit', command=self.quit).grid(row=i, column=0, sticky=W, pady=4)
def populate(self):
names = {'a','long','list','of','names','here'}
self.makeform(names)
self.frame.columnconfigure(1, weight=1)
self.frame.grid_columnconfigure(1, weight=1)
if __name__ == "__main__":
entries = {}
root=Tk()
test(root).pack(side="top", fill="both", expand=True)
root.mainloop()
您的代码中至少存在三个问题。
首先,要滚动的框架必须是 canvas 的一部分。不能用pack
或grid
放在canvas里,必须用create_window
。您正在调用 create_window
,但没有告诉它要添加什么 window。
其次,滚动条是框架的子项,但我假设这些是您想要滚动 canvas 的滚动条。需要在inner frame之外,在canvas.
之外
第三,您需要设置到 canvas 的 <Configure>
事件的绑定,以便您可以调整内部框架的大小并重新计算 canvas 的滚动区域。
可滚动框架的完整工作示例在这个答案中:
我需要这个简单的表格来: 1) 调整 window 大小时正确扩展字段和 2) 正确滚动字段列表。
我已经尝试了所有我能想到的方法,但上述 2 个条件中只有 1 个是正确的。此代码可以正确展开但不会滚动。没有 frame2,并将字段添加到 frame 或 canvas 则相反。
class test(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def makeform(self, root, fields):
i = 0
for field in fields:
Label(root, text=field + ": ", anchor=W).grid(row=i)
entry = Entry(root)
entry.grid(row=i, column=1, sticky=E+W)
entries[field] = entry
i += 1
def initialize(self):
frame = Frame(self)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
frame.grid(sticky=N+S+E+W)
canvas = Canvas(frame, width=900, height=800, bg='pink')
canvas.grid(row=0, column=0, sticky=N+S+E+W)
canvas.columnconfigure(0,weight=1)
canvas.rowconfigure(0,weight=1)
frame2 = Frame(canvas)
frame2.grid(row=0, column=0, sticky=N+S+E+W)
frame2.columnconfigure(1, weight=1)
vscrollbar = Scrollbar(frame2,orient=VERTICAL)
vscrollbar.grid(row=0, column=2, sticky=N+S)
vscrollbar.config(command=canvas.yview)
canvas.configure(yscrollcommand=vscrollbar.set)
self.grid_rowconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
names = {'a','long','list','of','names','here'}
self.makeform(frame2, names)
Button(self, text='Quit', command=self.quit).grid(row=1, column=0, sticky=W, pady=4)
canvas.create_window(0, 0)
canvas.config(scrollregion=canvas.bbox(ALL))
self.grid()
if __name__ == "__main__":
entries = {}
app = test(None)
app.title('Hi ')
app.mainloop()
更新
整合下面的 Bryan 示例,这适用于滚动,但在 window 调整大小时不会扩展字段。我尝试将 weight=1 添加到框架的第二列,但没有帮助。如何防止边框缩小?
class test(Tkinter.Frame):
def __init__(self,parent):
Tkinter.Frame.__init__(self, root)
self.canvas = Tkinter.Canvas(root, borderwidth=0, background="#ffffff")
self.frame = Tkinter.Frame(self.canvas, background="#ffffff")
self.vsb = Tkinter.Scrollbar(root, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((0,0), window=self.frame, anchor="nw",
tags="self.frame")
self.frame.bind("<Configure>", self.onFrameConfigure)
self.populate()
def onFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def makeform(self, fields):
i = 0
for field in fields:
Label(self.frame, text=field + ": ", anchor=W).grid(row=i)
entry = Entry(self.frame)
entry.grid(row=i, column=1, sticky=E+W)
entries[field] = entry
i += 1
Button(self.frame, text='Quit', command=self.quit).grid(row=i, column=0, sticky=W, pady=4)
def populate(self):
names = {'a','long','list','of','names','here'}
self.makeform(names)
self.frame.columnconfigure(1, weight=1)
self.frame.grid_columnconfigure(1, weight=1)
if __name__ == "__main__":
entries = {}
root=Tk()
test(root).pack(side="top", fill="both", expand=True)
root.mainloop()
您的代码中至少存在三个问题。
首先,要滚动的框架必须是 canvas 的一部分。不能用pack
或grid
放在canvas里,必须用create_window
。您正在调用 create_window
,但没有告诉它要添加什么 window。
其次,滚动条是框架的子项,但我假设这些是您想要滚动 canvas 的滚动条。需要在inner frame之外,在canvas.
之外第三,您需要设置到 canvas 的 <Configure>
事件的绑定,以便您可以调整内部框架的大小并重新计算 canvas 的滚动区域。
可滚动框架的完整工作示例在这个答案中: