How to pass arguments to a Button command in Tkinter?
假设我有以下用Tkinter在python中制作的
1 2 3 4 | import Tkinter as Tk win = Tk.Toplevel() frame = Tk.Frame(master=win).grid(row=1, column=1) button = Tk.Button(master=frame, text='press', command=action) |
当我按下按钮时调用方法
我已尝试使用以下代码:
1 | button = Tk.Button(master=frame, text='press', command=action(someNumber)) |
这只会立即调用该方法,按下按钮什么也不做。
在这种情况下,我个人更喜欢使用
这就是使用lambda的方法(请注意,函数模块中也有一些curring的实现,因此您也可以使用它):
1 | button = Tk.Button(master=frame, text='press', command= lambda: action(someNumber)) |
这也可以通过使用标准库功能工具中的
1 2 3 4 | from functools import partial #(...) action_with_arg = partial(action, arg) button = Tk.Button(master=frame, text='press', command=action_with_arg) |
python为函数参数提供默认值的能力为我们提供了一条出路。
1 2 3 | def fce(x=myX, y=myY): myFunction(x,y) button = Tk.Button(mainWin, text='press', command=fce) |
请参阅:http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/extra-args.html
对于更多按钮,可以创建返回函数的函数:
1 2 3 4 5 6 7 8 9 10 11 | def fce(myX, myY): def wrapper(x=myX, y=myY): pass pass pass return x+y return wrapper button1 = Tk.Button(mainWin, text='press 1', command=fce(1,2)) button2 = Tk.Button(mainWin, text='press 2', command=fce(3,4)) button3 = Tk.Button(mainWin, text='press 3', command=fce(9,8)) |
示例图形用户界面:
假设我有图形用户界面:
1 2 3 4 5 6 7 8 | import tkinter as tk root = tk.Tk() btn = tk.Button(root, text="Press") btn.pack() root.mainloop() |
按下按钮会发生什么
请注意,当按下
1 2 3 | def button_press_handle(callback=None): if callback: callback() # Where exactly the method assigned to btn['command'] is being callled |
用:
1 | button_press_handle(btn['command']) |
您可以简单地认为,
没有参数
因此,如果我想在按下按钮时输入1〔5〕的内容,我需要设置:
1 | btn['command'] = print # default to print is new line |
注意
带参数
现在,如果我还想向按下按钮时要调用的方法传递参数,我可以使用匿名函数(可以用lambda语句创建),在本例中,对于
1 | btn['command'] = lambda arg1="Hello", arg2="", arg3="World!" : print(arg1 + arg2 + arg3) |
按下按钮时调用多个方法
没有参数
您也可以使用
1 2 3 | def multiple_methods(): print("Vicariously") # the first inner callback print("I") # another inner callback |
带参数
为了将参数传递给调用其他方法的方法,再次使用
1 2 3 | def multiple_methods(*args, **kwargs): print(args[0]) # the first inner callback print(kwargs['opt1']) # another inner callback |
然后设置:
1 | btn['command'] = lambda arg="live", kw="as the" : a_new_method(arg, opt1=kw) |
从回调返回对象
还需要注意的是,
下面的示例将调用每次按下按钮时更改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import tkinter as tk i = 0 def text_mod(): global i, btn # btn can be omitted but not sure if should be txt = ("Vicariously","I","live","as","the","whole","world","dies") btn['text'] = txt[i] # the global object that is modified i = (i + 1) % len(txt) # another global object that gets modified root = tk.Tk() btn = tk.Button(root, text="My Button") btn['command'] = text_mod btn.pack(fill='both', expand=True) root.mainloop() |
镜子
1 | button = Tk.Button(master=frame, text='press', command=lambda: action(someNumber)) |
我想应该解决这个问题
一种简单的方法是使用
1 | button['command'] = lambda arg1 = local_var1, arg2 = local_var2 : function(arg1, arg2) |
它立即调用该方法并且按下按钮不执行任何操作的原因是,对
要使用按钮调用具有不同参数的函数,可以使用全局变量,尽管我不推荐这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import Tkinter as Tk frame = Tk.Frame(width=5, height=2, bd=1, relief=Tk.SUNKEN) frame.grid(row=2,column=2) frame.pack(fill=Tk.X, padx=5, pady=5) def action(): global output global variable output.insert(Tk.END,variable.get()) button = Tk.Button(master=frame, text='press', command=action) button.pack() variable = Tk.Entry(master=frame) variable.pack() output = Tk.Text(master=frame) output.pack() if __name__ == '__main__': Tk.mainloop() |
我要做的是制作一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import Tkinter as Tk class Window: def __init__(self): self.frame = Tk.Frame(width=5, height=2, bd=1, relief=Tk.SUNKEN) self.frame.grid(row=2,column=2) self.frame.pack(fill=Tk.X, padx=5, pady=5) self.button = Tk.Button(master=self.frame, text='press', command=self.action) self.button.pack() self.variable = Tk.Entry(master=self.frame) self.variable.pack() self.output = Tk.Text(master=self.frame) self.output.pack() def action(self): self.output.insert(Tk.END,self.variable.get()) if __name__ == '__main__': window = Window() Tk.mainloop() |
我迟到了,但这是一个很简单的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import tkinter as tk def function1(param1, param2): print(str(param1) + str(param2)) var1 ="Hello" var2 ="World!" def function2(): function1(var1, var2) root = tk.Tk() myButton = tk.Button(root, text="Button", command=function2) root.mainloop() |
只需将要在另一个函数中使用的函数包装起来,然后调用按钮上的第二个函数。
最好使用lambda,如下所示:
1 | button = Tk.Button(master=frame, text='press', command=lambda: action(someNumber)) |
基于Matt Thompson的回答:可以使类可调用,这样就可以使用它而不是函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import tkinter as tk class Callback: def __init__(self, func, *args, **kwargs): self.func = func self.args = args self.kwargs = kwargs def __call__(self): self.func(*self.args, **self.kwargs) def default_callback(t): print("Button '{}' pressed.".format(t)) root = tk.Tk() buttons = ["A","B","C"] for i, b in enumerate(buttons): tk.Button(root, text=b, command=Callback(default_callback, b)).grid(row=i, column=0) tk.mainloop() |
对于后代:您也可以使用类来实现类似的事情。例如:
1 2 3 4 5 | class Function_Wrapper(): def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def func(self): return self.x + self.y + self.z # execute function |
按钮可以通过以下方式简单地创建:
1 2 | instance1 = Function_Wrapper(x, y, z) button1 = Button(master, text ="press", command = instance1.func) |
这种方法还允许您通过设置
杰森比-一些事情…
如果你在一个循环中插入一个按钮,它将被一次又一次地创建…这可能不是你想要的。(也许是这样)
它总是得到最后一个索引的原因是当您单击lambda事件时运行,而不是当程序启动时。我不确定你在做什么,但可能尝试在生成值时存储它,然后用lambda按钮稍后调用它。
(不要使用这个代码,只是一个例子)
1 2 | for entry in stuff_that_is_happening: value_store[entry] = stuff_that_is_happening |
然后你可以说……
1 | button... command: lambda: value_store[1] |
希望这有帮助!
如果要执行更多操作,请使用lambda将输入数据传递给command函数,如以下所示(我试图使其成为通用的,因此只需进行调整):
1 2 3 4 5 6 7 8 9 | event1 = Entry(master) button1 = Button(master, text="OK", command=lambda: test_event(event1.get())) def test_event(event_text): if not event_text: print("Nothing entered") else: print(str(event_text)) # do stuff |
这会将事件中的信息传递给按钮功能。写这篇文章的方式可能更多,但对我有用。