【问题标题】:How to access the frame outside the function in python如何在python中访问函数外部的框架
【发布时间】:2021-09-18 22:12:34
【问题描述】:

如何在函数外部访问 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()里面?
  • 如果scroll_frame是new_frame的父级,那么它必须在new_frame之前创建。
  • @acw1668,因为我想要很多帧的滚动条,我不想一次又一次地使用相同的代码。这就是为什么我制作了一个滚动功能,以便将每个新创建的框架放入滚动框架中
  • @8349697,是的,我知道这一点。但我只想制作一次滚动功能,并在必要时使用它。所以请告诉我这个函数是如何工作的。
  • 尝试从函数中返回创建的scroll_frame对象。

标签: python tkinter scrollbar frame


【解决方案1】:

如果你想访问scroll_frame,你应该从scroll()返回。

建议也返回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(),最好使用类而不是函数。


更新:使用类实现:

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。关于 new_frame 我不确定,我需要检查它是否可能在我的代码中。我对 OOP 很陌生,我现在才开始使用 OOP 一个星期。你能告诉我怎么做吗?
  • 我不明白为什么你建议将父级传递给 scroll() 而不是硬编码的根目录。你能解释一下你在这行中做了什么,container,scroll_frame = scroll(root)。
  • 如果你以后想在另一个窗口中使用这个滚动功能,硬编码的root是无法实现的。对于第二个问题,由于scroll() 现在返回两个对象(实际上是两个帧的元组),container, scroll_frame = scroll(root) 将通过scroll() 将返回的元组解包为containerscroll_frame
  • 嘿,谢谢你的解释。您能告诉我如何将这段代码集成到 OOP 方法中吗?
  • 答案已更新为类实现。
【解决方案2】:

@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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-24
    • 2017-06-01
    • 2020-10-30
    • 2017-04-11
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2021-08-24
    相关资源
    最近更新 更多