如何在 Tkinter 中将参数传递给 Button 命令?
假设我在 Python 中使用 Tkinter 制作了以下 Button
:
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)
当我按下按钮时,会调用方法 action
,但是如果我想将一些参数传递给方法 action
,该怎么办?代码>操作?
我尝试使用以下代码:
button = Tk.Button(master=frame, text='press', command=action(someNumber))
这只是立即调用该方法,按下按钮不会执行任何操作。
请参阅 Python 参数绑定器,了解解决问题的标准技术(不是 Tkinter 特定的)。在 Tkinter(或其他 GUI 框架)中使用回调有一些特殊的注意事项,因为回调的返回值是无用的。
如果您尝试在循环中创建多个按钮,则根据循环计数器,您可能会遇到由于所谓的后期绑定而出现的问题。有关详细信息,请参阅 tkinter 在 for 循环中传递命令参数创建按钮。
Suppose I have the following Button
made with Tkinter in Python:
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)
The method action
is called when I press the button, but what if I wanted to pass some arguments to the method action
?
I have tried with the following code:
button = Tk.Button(master=frame, text='press', command=action(someNumber))
This just invokes the method immediately, and pressing the button does nothing.
See Python Argument Binders for standard techniques (not Tkinter-specific) for solving the problem. Working with callbacks in Tkinter (or other GUI frameworks) has some special considerations because the return value from the callback is useless.
If you try to create multiple Buttons in a loop, passing each one different arguments based on the loop counter, you may run into problems due to what is called late binding. Please see tkinter creating buttons in for loop passing command arguments for details.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
这可以使用 lambda 来完成,如下所示:
这是一种绑定参数的简单方法,无需显式包装方法或修改原始操作。
This can be done using a
lambda
, like so:This is a simple way to bind the argument without an explicit wrapper method or modifying the original
action
.这也可以通过使用标准库 functools 中的
partial
来完成,例如这:This can also be done by using
partial
from the standard library functools, like this:GUI 示例:
假设我有 GUI:
按下按钮时会发生什么
看到按下
btn
时,它会调用自己的函数,该函数与非常相似下面例子中的button_press_handle
:with:
你可以简单的认为
command
选项应该设置为,对我们想要调用的方法的引用,类似于callback中
button_press_handle
。按下按钮时调用方法(回调)
没有 参数
因此,如果我想在按下按钮时
打印
某些内容,我需要设置:密切注意
lack >()
与print
方法被省略,其含义是:“这是我希望您在按下时调用的方法名称但是不要这么称呼它然而,我没有为print
传递任何参数,因此它会打印在不带参数调用时打印的任何内容。带有参数
现在,如果我还想在按下按钮时将参数传递给我想要调用的方法,我可以这样做使用匿名函数,可以使用 lambda 语句创建,在本例中为
print
内置方法,如下所示:按下按钮时调用多个方法
不带参数
您还可以使用
lambda
语句来实现但这被认为是不好的做法,因此我不会将其包含在这里。好的做法是定义一个单独的方法multiple_methods
,它调用所需的方法,然后将其设置为按钮按下的回调:With Argument(s )
为了将参数传递给调用其他方法的方法,请再次使用 lambda 语句,但首先:
然后设置:
从回调返回对象
还 进一步注意
回调
不能真正return
,因为它仅在button_press_handle
内部使用callback()
调用,而不是return callback()
。它确实返回
,但不在该函数之外的任何地方。因此,您应该修改当前范围内可访问的对象。完整示例 全局 对象修改
下面的示例将调用一个方法,该方法会在每次按下按钮时更改
btn
的文本:镜像
Example GUI:
Let's say I have the GUI:
What Happens When a Button Is Pressed
See that when
btn
is pressed it calls its own function which is very similar tobutton_press_handle
in the following example:with:
You can simply think that
command
option should be set as, the reference to the method we want to be called, similar tocallback
inbutton_press_handle
.Calling a Method(Callback) When the Button is Pressed
Without arguments
So if I wanted to
print
something when the button is pressed I would need to set:Pay close attention to the lack of
()
with theprint
method which is omitted in the meaning that: "This is the method's name which I want you to call when pressed but don't call it just this very instant." However, I didn't pass any arguments for theprint
so it printed whatever it prints when called without arguments.With Argument(s)
Now If I wanted to also pass arguments to the method I want to be called when the button is pressed I could make use of the anonymous functions, which can be created with lambda statement, in this case for
print
built-in method, like the following:Calling Multiple Methods when the Button Is Pressed
Without Arguments
You can also achieve that using
lambda
statement but it is considered bad practice and thus I won't include it here. The good practice is to define a separate method,multiple_methods
, that calls the methods wanted and then set it as the callback to the button press:With Argument(s)
In order to pass argument(s) to method that calls other methods, again make use of
lambda
statement, but first:and then set:
Returning Object(s) From the Callback
Also further note that
callback
can't reallyreturn
because it's only called insidebutton_press_handle
withcallback()
as opposed toreturn callback()
. It doesreturn
but not anywhere outside that function. Thus you should rather modify object(s) that are accessible in the current scope.Complete Example with global Object Modification(s)
Below example will call a method that changes
btn
's text each time the button is pressed:Mirror
Python 为函数参数提供默认值的能力为我们提供了一条出路。
:https://tkdocs.com/shipman/extra-args.html
请参阅 更多按钮,您可以创建一个返回函数的函数:
Python's ability to provide default values for function arguments gives us a way out.
See: https://tkdocs.com/shipman/extra-args.html
For more buttons you can create a function which returns a function:
只是为了使 Nae 的答案更详细一些,这里有一个完整的示例,其中包括将变量传递给回调的可能性,该回调包含每个按钮的不同值:
通过定义临时变量 ztemp,该变量的值在定义按钮时就固定了。
Just to make the answer of Nae a little bit more elaborate, here is a full blown example which includes the possibility to pass a variable to the callback which contains different values for each button:
By defining a temporary variable ztemp, the value of that variable gets fixed at the moment when the button is defined.
以马特·汤普森的答案为基础:可以将类设为可调用,以便可以使用它来代替函数:
Building on Matt Thompsons answer : a class can be made callable so it can be used instead of a function:
使用 lambda
输出:
Use lambda
output:
Lambda 都很好,但您也可以尝试这个(顺便说一句,它在 for 循环中工作):
这是有效的,因为当设置绑定时,按键会将事件作为参数传递。然后,您可以调用事件的属性,例如
event.char
来获取“1”或“UP”等。如果除了事件属性之外您还需要一个或多个参数。只需创建一个字典来存储它们即可。Lambdas are all well and good, but you can also try this (which works in a for loop btw):
This works because when the binding is set, a key press passes the event as an argument. You can then call attributes off the event like
event.char
to get "1" or "UP" ect. If you need an argument or multiple arguments other than the event attributes. just create a dictionary to store them.一种简单的方法是使用
lambda
配置button
,如下语法:One simple way would be to configure
button
withlambda
like the following syntax:它立即调用该方法并且按下按钮不执行任何操作的原因是对
action(somenumber)
进行了评估,并将其返回值归因于按钮的命令。因此,如果action
打印一些内容来告诉您它已运行并返回None
,您只需运行action
来评估其返回值并给出None
作为按钮的命令。要使用按钮来调用具有不同参数的函数,您可以使用全局变量,尽管我不推荐这样做:
我要做的是创建一个
class
,其对象将包含所需的每个变量以及更改这些变量的方法根据需要:The reason it invokes the method immediately and pressing the button does nothing is that
action(somenumber)
is evaluated and its return value is attributed as the command for the button. So ifaction
prints something to tell you it has run and returnsNone
, you just runaction
to evaluate its return value and givenNone
as the command for the button.To have buttons to call functions with different arguments you can use global variables, although I can't recommend it:
What I would do is make a
class
whose objects would contain every variable required and methods to change those as needed:我迟到了,但这是一个非常简单的方法来完成它。
您只需将要使用的函数包装在另一个函数中,然后在按下按钮时调用第二个函数即可。
I am extremely late, but here is a very simple way of accomplishing it.
You simply wrap the function you want to use in another function and call the second function on the button press.
另一种方法是定义一个类并使用实例属性来记住回调的参数。要实现回调,我们可以简单地使用类的一个方法,该方法从
self
查找属性值 - 它根本不需要有单独的参数。像这样创建类:
然后创建像这样的按钮:
这种方法还允许稍后通过简单地修改类实例来更改参数绑定:
Another way is by defining a class and using instance attributes to remember arguments for the callback. To implement the callback, we can simply use a method of the class which looks up the attribute values from
self
- it doesn't need to have separate parameters at all.Create the class like so:
Then make buttons like:
This approach also allows changing the argument bindings later by simply modifying the class instance:
如果您有更多操作要执行,请使用 lambda 将输入数据传递给命令函数,如下所示(我已尝试使其通用,因此只需调整):
这会将事件中的信息传递给按钮函数。可能还有更多Python式的写法,但它对我有用。
Use a lambda to pass the entry data to the command function if you have more actions to carry out, like this (I've tried to make it generic, so just adapt):
This will pass the information in the event to the button function. There may be more Pythonesque ways of writing this, but it works for me.
首先:如果将创建按钮的代码放入循环中,则每次循环都会重新创建
Button
实例,这可能是理想的,也可能不是理想的。它总是获取最后一个索引的原因是回调在单击按钮时运行,而不是在程序启动时运行。尝试在创建按钮时存储变量的值,然后让 lambda 使用存储的值。
例如:
然后,后来:
First: if the code to create a button is put in a loop, the
Button
instance will be re-created each time through the loop, which may or may not be desirable.The reason it always gets the last index is that the callback runs when the button is clicked, not when the program starts. Try storing the value of the variable when the button is created, then have the
lambda
use the stored value.For example:
Then, later: