如何将传递回调推广到tkinter笔记本中



我试图推广在tkinter.ttk.Notebook中添加按钮和选项卡。到目前为止,我拥有的是:

from tkinter.ttk import Notebook, Frame
from tkinter import Button, Tk
f1 = lambda: print("f1")
f2 = lambda: print("f2")
f3 = lambda: print("f3")
f4 = lambda: print("f4")
f5 = lambda: print("f5")
f6 = lambda: print("f6")
f7 = lambda: print("f7")
frames = ["F1", "F2", "F3"]
labels = [('f1', 'f2', 'f3'), ('f4', 'f5'), ('f6', 'f7')]
commands = [(f1, f2, f3), (f4, f5), (f6, f7)]
tk = Tk()
notebook = Notebook(tk)
for i, f in enumerate(frames):
frame = Frame(notebook)
notebook.add(frame, text=f)
for j, label in enumerate(labels[i]):
button = Button(frame, text=label, command=commands[i][j])
button.pack()
notebook.pack()
tk.mainloop()

现在,假设我希望函数f7不打印字符串'f7',而是执行frame.quit,这样我就可以退出笔记本了。

如何调用frame.quit并保持上面代码的泛型?在for循环之前,我不知道该怎么做。

我想到了两种方法。第一种是在lambdas之前创建一个空对象(使用此处描述的方法(,然后在调用frame时正确定义该函数。

frame = type('', (), {})()
f1 = lambda: print("f1")
f2 = lambda: print("f2")
f3 = lambda: print("f3")
f4 = lambda: print("f4")
f5 = lambda: print("f5")
f6 = lambda: print("f6")
f7 = lambda: print(frame.quit)

如果你的几个函数要引用这个框架,你可以把一个引用传递给它,但每个lambda都需要把它作为一个参数。

from tkinter.ttk import Notebook, Frame
from tkinter import Button, Tk
f1 = lambda f: print("f1")
f2 = lambda f: print("f2")
f3 = lambda f: print("f3")
f4 = lambda f: print("f4")
f5 = lambda f: print("f5")
f6 = lambda f: print("f6")
f7 = lambda f: f.quit()

frames = ["F1", "F2", "F3"]
labels = [('f1', 'f2', 'f3'), ('f4', 'f5'), ('f6', 'f7')]
commands = [(f1, f2, f3), (f4, f5), (f6, f7)]
tk = Tk()
notebook = Notebook(tk)
for i, f in enumerate(frames):
frame = Frame(notebook)
notebook.add(frame, text=f)
for j, label in enumerate(labels[i]):
button = Button(frame, text=label, command= lambda: commands[i][j](frame))
button.pack()
notebook.pack()
tk.mainloop()

您需要进行一些更改来支持您想要的内容。

  1. 为定义的七个默认F*函数中的每一个添加一个通用*args参数,这样,如果有任何参数传递给它们(如frame(,它们就会工作
  2. commands变量从元组列表更改为列表列表,以使其子序列可变
  3. 使Buttoncommand=关键字参数值为lambda,并包含多个参数,其中一些参数具有默认值。这使它能够在运行时查找值
from tkinter.ttk import Notebook, Frame
from tkinter import Button, Tk
f1 = lambda *args: print("f1")
f2 = lambda *args: print("f2")
f3 = lambda *args: print("f3")
f4 = lambda *args: print("f4")
f5 = lambda *args: print("f5")
f6 = lambda *args: print("f6")
f7 = lambda *args: print("f7")
frames = ["F1", "F2", "F3"]
labels = [('f1', 'f2', 'f3'), ('f4', 'f5'), ('f6', 'f7')]
commands = [[f1, f2, f3], [f4, f5], [f6, f7]]  # CHANGED TO LIST OF SUBLISTS
tk = Tk()
notebook = Notebook(tk)
for i, f in enumerate(frames):
frame = Frame(notebook)
notebook.add(frame, text=f)
for j, label in enumerate(labels[i]):
button = Button(frame, text=label, command=lambda i=i, j=j: commands[i][j](frame))
button.pack()
notebook.pack()
commands[2][1] = lambda frame: frame.quit()  # Change the F7 slot.
tk.mainloop()

我做了一些稍微不同的事情,它起了作用:

from tkinter.ttk import Notebook, Frame
from tkinter import Button, Tk
tk = Tk()
notebook = Notebook(tk)
f1 = lambda: print("f1")
f2 = lambda: print("f2")
f3 = lambda: print("f3")
f4 = lambda: print("f4")
f5 = lambda: print("f5")
f6 = lambda: print("f6")
f7 = lambda: notebook.quit()
frames = ["F1", "F2", "F3"]
labels = [('f1', 'f2', 'f3'), ('f4', 'f5'), ('f6', 'f7')]
commands = [(f1, f2, f3), (f4, f5), (f6, f7)]
for i, f in enumerate(frames):
frame = Frame(notebook)
notebook.add(frame, text=f)
for j, label in enumerate(labels[i]):
button = Button(frame, text=label, command=commands[i][j])
button.pack()
notebook.pack()
tk.mainloop()

最新更新