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()
# !/usr/bin/python
# coding=utf-8
from Tkinter import *
# Creation de la fenêtre principale (main window)
Mafenetre = Tk()
res1 = StringVar()
res2 = StringVar()
def isValidInput(obj):
if hasattr(obj, 'get') and callable(getattr(obj, 'get')):
return TRUE
return FALSE
# stupid action 2 (return 12 on purpose to show potential mistake)
def action1(*arguments):
print "action1 running"
for arg in arguments:
if isValidInput(arg):
print "input value: ", arg.get()
res1.set(arg.get())
else:
print "other value:", arg
print "\n"
return 12
# stupid action 2
def action2(*arguments):
print "action2 running"
a = arguments[0]
b = arguments[1]
if isValidInput(a) and isValidInput(b):
c = a.get() + b.get()
res2.set(c)
print c
print "\n"
# a stupid workflow manager ordered by name
def start_tasks(*arguments,**keywords):
keys = sorted(keywords.keys())
for kw in keys:
print kw, "plugged "
keywords[kw](*arguments)
# valid callback wrapper with lambda
def action1_callback(my_input):
return lambda args=[my_input]: action1(*args)
# valid callback wrapper without lambda
def action1_callback_nolambda(*args,**kw):
def anon():
action1(*args)
return anon
# first input string
input1 = StringVar()
input1.set("delete me...")
f1 = Entry(Mafenetre, textvariable=input1, bg='bisque', fg='maroon')
f1.focus_set()
f1.pack(fill="both", expand="yes", padx="5", pady=5)
# failed callback because the action1 function is evaluated, it will return 12.
# in this case the button won't work at all, because the assignement expect a function
# in order to have the button command to execute something
ba1 = Button(Mafenetre)
ba1['text'] = "show input 1 (ko)"
ba1['command'] = action1(input1)
ba1.pack(fill="both", expand="yes", padx="5", pady=5)
# working button using a wrapper
ba3 = Button(Mafenetre)
ba3['text'] = "show input 1 (ok)"
# without a lambda it is also working if the assignment is a function
# ba1['command'] = action1_callback_nolambda(input1)
ba3['command'] = action1_callback(input1)
ba3.pack(fill="both", expand="yes", padx="5", pady=5)
# display result label
Label1 = Label(Mafenetre, text="Action 1 result:")
Label1.pack(fill="both", expand="yes", padx="5", pady=5)
# display result value
resl1 = Label(Mafenetre, textvariable=res1)
resl1.pack(fill="both", expand="yes", padx="5", pady=5)
# second input string
input2 = StringVar()
f2 = Entry(Mafenetre, textvariable=input2, bg='bisque', fg='maroon')
f2.focus_set()
f2.pack(fill="both", expand="yes", padx="5", pady=5)
# third test without wrapper, but making sure that several arguments are well handled by a lambda function
ba2 = Button(Mafenetre)
ba2['text'] = "execute action 2"
ba2['command'] = lambda args=[input1, input2], action=action2: start_tasks(*args, do=action)
ba2.pack(fill="both", expand="yes", padx="5", pady=5)
# display result label
Label2 = Label(Mafenetre, text="Action 2 result:")
Label2.pack(fill="both", expand="yes", padx="5", pady=5)
# display result value
resl2 = Label(Mafenetre, textvariable=res2)
resl2.pack(fill="both", expand="yes", padx="5", pady=5)
Mafenetre.mainloop()
5条答案
按热度按时间0sgqnhkj1#
考虑这个代码:
它的作用与此完全相同:
同样,如果创建如下绑定:
... 与此相同:
这个
command
选项获取对函数的引用,这是一种奇特的方式,表示需要将函数名传递给它。若要传递引用,必须仅使用名称,而不使用括号或参数。例如:如果要传递诸如“hey”之类的参数,则必须使用一些额外的代码:
您可以创建一个中间函数,该函数可以在没有参数的情况下调用,然后调用
button
功能,你可以用
lambda
创建所谓的匿名函数。从各个方面来说,它都是一个函数,只是它没有名字。当你打电话给lambda
命令返回对所创建函数的引用,这意味着它可以用于command
选择该按钮。您可以使用functools.partial
为了我,
lambda
是最简单的,因为它不需要像functools.partial
是吗,尽管有些人认为functools.partial
更容易理解。创建一个lambda函数来调用
button
函数的参数,您可以执行以下操作:最终得到的函数在功能上等同于:
正如我刚才所说,
lambda
返回对此无名函数的引用。既然引用是command
选项期望您可以使用lambda
直接在按钮的创建中:在这个网站上有一个问题,关于lambda总的来说有很多有趣的评论。查看python lambda为什么有用的问题?。同样的讨论有一个答案,说明了当您需要将变量传递给回调函数时,如何在循环中使用lambdas。
最后,请参阅effbot.org上标题为tkinter回调的部分,以获得一个不错的教程。lambda的覆盖范围非常小,但其中的信息可能仍然有用。
htzpubme2#
您需要创建一个不带参数的函数,该函数可以用作命令:
请参阅本文档的“将参数传递给回调”部分。
f4t66c6m3#
图形用户界面示例:
假设我有gui:
按下按钮时会发生什么
看到了吗
btn
按下按钮后,它会调用自己的函数,这与button_press_handle
在以下示例中:与:
你可以这么想
command
选项应设置为,我们希望调用的方法的引用,类似于callback
在里面button_press_handle
.按下按钮时调用方法(回调)
毫无争议
所以如果我想
print
按下按钮时,我需要设置:密切注意缺乏必要的信息
()
和print
方法,该方法被省略,意思是:“这是我希望您在按下时调用的方法名称,但不要立即调用它。”但是,我没有为print
因此,它在没有参数的情况下打印调用时打印的任何内容。带参数
现在,如果我还想将参数传递给我想在按下按钮时被调用的方法,我可以使用匿名函数,它可以用lambda语句创建,在本例中,用于
print
内置方法,如下所示:按下按钮时调用多个方法
毫无争议
您还可以使用
lambda
声明,但这被认为是不好的做法,因此我不会在这里包括它。好的做法是定义一个单独的方法,multiple_methods
,调用所需的方法,然后将其设置为对按钮按下的回调:带参数
为了将参数传递给调用其他方法的方法,请再次使用
lambda
声明,但首先:然后设置:
从回调返回对象
还进一步注意到
callback
不可能return
因为它只在里面叫button_press_handle
具有callback()
相对于return callback()
. 是的return
但在该功能之外的任何地方都不能。因此,您应该修改在当前范围内可访问的对象。具有全局对象修改的完整示例
下面的示例将调用一个发生更改的方法
btn
每次按下按钮时的文本:镜子
nwlls2ji4#
当引擎在“…”行赋值时,它会评估函数的结果。。。命令=…”
“command”要求返回一个函数,这就是为什么使用lambda可以完成这项工作,因为它正在创建一个在求值期间返回给“command”的异常函数。您还可以编写自己的函数,它也可以完成这项工作。
这是一个有lambda和没有lambda的示例:
neskvpey5#
我认为解决这个问题的最好方法是使用lambda函数。
如果不想使用command关键字,可以改用.bind()方法:
使用拥有要调用的子函数(至少1个参数)的母函数(无参数)是愚蠢的。
为了与大家分享,这是我的一个计划:
就这样。