如何在 python 中访问函数外部的框架
How to access the frame outside the function in python
如何在函数外部访问 scroll_frame,以便 new_frame 位于下面代码中的 scroll_frame 内部。
def scroll():
container = LabelFrame(root)
my_canvas = Canvas(container)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
scroll_y = Scrollbar(container, orient=VERTICAL, command=my_canvas.yview)
scroll_y.pack(side=RIGHT, fill='y')
my_canvas.configure(yscrollcommand=scroll_y.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox('all')))
scroll_frame = Frame(my_canvas)
my_canvas.create_window((0, 0), window=scroll_frame, anchor=NW)
container.pack(fill=BOTH, expand=1)
new_frame = Frame(scroll_frame)
for i in range(25):
Button(new_frame, text='click'+str(i)).pack()
scroll()
root.mainloop()
如果您想访问 scroll_frame
,您应该从 scroll()
.
return
也建议return container
不要在scroll()
里面调用container.pack(...)
因为这样比较灵活
还建议将父级也传递给 scroll()
,而不是在其中硬编码 root
。
from tkinter import *
def scroll(parent):
container = LabelFrame(parent)
my_canvas = Canvas(container, highlightthickness=0)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
scroll_y = Scrollbar(container, orient=VERTICAL, command=my_canvas.yview)
scroll_y.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=scroll_y.set)
scroll_frame = Frame(my_canvas)
my_canvas.create_window((0, 0), window=scroll_frame, anchor=NW)
# bind <Configure> on scroll_frame instead of my_canvas
scroll_frame.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox('all')))
return container, scroll_frame
root = Tk()
container, scroll_frame = scroll(root)
container.pack(fill=BOTH, expand=1)
# Is new_frame necessary? Why not use scroll_frame directly?
new_frame = Frame(scroll_frame)
new_frame.pack()
for i in range(25):
Button(new_frame, text='click'+str(i)).pack(fill=X)
root.mainloop()
注意,如果要重复使用scroll()
,最好使用class而不是函数。
更新:使用 class 实现:
import tkinter as tk
class ScrollableFrame(tk.LabelFrame):
def __init__(self, parent, **kw):
super().__init__(parent, **kw)
canvas = tk.Canvas(self, highlightthickness=0)
canvas.pack(side="left", fill="both", expand=1)
vscrollbar = tk.Scrollbar(self, orient="vertical", command=canvas.yview)
vscrollbar.pack(side="right", fill="y")
canvas.config(yscrollcommand=vscrollbar.set)
self.scroll_frame = tk.Frame(canvas)
self.scroll_frame.bind("<Configure>", lambda e: canvas.config(scrollregion=canvas.bbox("all")))
canvas.create_window(0, 0, window=self.scroll_frame, anchor="nw")
if __name__ == "__main__":
root = tk.Tk()
container = ScrollableFrame(root)
container.pack(fill="both", expand=1)
for i in range(25):
tk.Button(container.scroll_frame, text=f"click {i}").pack(fill="x")
root.mainloop()
@acw1668 的解决方案很好,但我无法在我想要的框架中制作滚动条。
所以最后我得出了这个:
from tkinter import * # you should avoid wildcard import
root = Tk()
f1 = Frame(root)
t1 = Text(root)
f2 = Frame(root)
t2 = Text(root)
def scroll(in_frame, lbl, txt):
in_frame_lbl = Label(in_frame, text=lbl)
in_frame_lbl.pack(fill=X)
in_frame.pack(fill=X)
scroll_y = Scrollbar(in_frame, orient=VERTICAL)
scroll_y.pack(side=RIGHT, anchor=N, fill=Y)
txt.config(yscrollcommand=scroll_y.set)
txt.pack(fill=X)
scroll_y.config(command=txt.yview)
txt.config(state='disabled')
scroll(f1, 'Scroll in Frame 1', t1)
scroll(f2, 'Scroll in Frame 2', t2)
for i in range(5):
Button(f1, text='click'+str(i)).pack(fill=X)
Entry(f2).pack()
root.mainloop()
如何在函数外部访问 scroll_frame,以便 new_frame 位于下面代码中的 scroll_frame 内部。
def scroll():
container = LabelFrame(root)
my_canvas = Canvas(container)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
scroll_y = Scrollbar(container, orient=VERTICAL, command=my_canvas.yview)
scroll_y.pack(side=RIGHT, fill='y')
my_canvas.configure(yscrollcommand=scroll_y.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox('all')))
scroll_frame = Frame(my_canvas)
my_canvas.create_window((0, 0), window=scroll_frame, anchor=NW)
container.pack(fill=BOTH, expand=1)
new_frame = Frame(scroll_frame)
for i in range(25):
Button(new_frame, text='click'+str(i)).pack()
scroll()
root.mainloop()
如果您想访问 scroll_frame
,您应该从 scroll()
.
也建议return container
不要在scroll()
里面调用container.pack(...)
因为这样比较灵活
还建议将父级也传递给 scroll()
,而不是在其中硬编码 root
。
from tkinter import *
def scroll(parent):
container = LabelFrame(parent)
my_canvas = Canvas(container, highlightthickness=0)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
scroll_y = Scrollbar(container, orient=VERTICAL, command=my_canvas.yview)
scroll_y.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=scroll_y.set)
scroll_frame = Frame(my_canvas)
my_canvas.create_window((0, 0), window=scroll_frame, anchor=NW)
# bind <Configure> on scroll_frame instead of my_canvas
scroll_frame.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox('all')))
return container, scroll_frame
root = Tk()
container, scroll_frame = scroll(root)
container.pack(fill=BOTH, expand=1)
# Is new_frame necessary? Why not use scroll_frame directly?
new_frame = Frame(scroll_frame)
new_frame.pack()
for i in range(25):
Button(new_frame, text='click'+str(i)).pack(fill=X)
root.mainloop()
注意,如果要重复使用scroll()
,最好使用class而不是函数。
更新:使用 class 实现:
import tkinter as tk
class ScrollableFrame(tk.LabelFrame):
def __init__(self, parent, **kw):
super().__init__(parent, **kw)
canvas = tk.Canvas(self, highlightthickness=0)
canvas.pack(side="left", fill="both", expand=1)
vscrollbar = tk.Scrollbar(self, orient="vertical", command=canvas.yview)
vscrollbar.pack(side="right", fill="y")
canvas.config(yscrollcommand=vscrollbar.set)
self.scroll_frame = tk.Frame(canvas)
self.scroll_frame.bind("<Configure>", lambda e: canvas.config(scrollregion=canvas.bbox("all")))
canvas.create_window(0, 0, window=self.scroll_frame, anchor="nw")
if __name__ == "__main__":
root = tk.Tk()
container = ScrollableFrame(root)
container.pack(fill="both", expand=1)
for i in range(25):
tk.Button(container.scroll_frame, text=f"click {i}").pack(fill="x")
root.mainloop()
@acw1668 的解决方案很好,但我无法在我想要的框架中制作滚动条。
所以最后我得出了这个:
from tkinter import * # you should avoid wildcard import
root = Tk()
f1 = Frame(root)
t1 = Text(root)
f2 = Frame(root)
t2 = Text(root)
def scroll(in_frame, lbl, txt):
in_frame_lbl = Label(in_frame, text=lbl)
in_frame_lbl.pack(fill=X)
in_frame.pack(fill=X)
scroll_y = Scrollbar(in_frame, orient=VERTICAL)
scroll_y.pack(side=RIGHT, anchor=N, fill=Y)
txt.config(yscrollcommand=scroll_y.set)
txt.pack(fill=X)
scroll_y.config(command=txt.yview)
txt.config(state='disabled')
scroll(f1, 'Scroll in Frame 1', t1)
scroll(f2, 'Scroll in Frame 2', t2)
for i in range(5):
Button(f1, text='click'+str(i)).pack(fill=X)
Entry(f2).pack()
root.mainloop()