2006年02月26日 星期日 16:40
Tkinter.Button(root, text='aaa', command=click) 中的 command 怎么加入参数啊? -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060226/36ada167/attachment.html
2006年02月26日 星期日 17:59
click(....)可以不? 在06-2-26,Gu Yingbo <tensiongyb at gmail.com> 写道: > > Tkinter.Button(root, text='aaa', command=click) > 中的 command 怎么加入参数啊? > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -- Andelf BLOG:http://blog.sohu.com/members/andelf/ BLOG:http://spaces.msn.com/members/andelf -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060226/f83b4975/attachment.htm
2006年02月26日 星期日 18:53
不可以 On 2/26/06, Andelf <andelf at gmail.com> wrote: > > click(....)可以不? > > 在06-2-26,Gu Yingbo <tensiongyb at gmail.com> 写道: > > > > Tkinter.Button(root, text='aaa', command=click) > > 中的 command 怎么加入参数啊? > > > > _______________________________________________ > > python-chinese > > Post: send python-chinese at lists.python.cn > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > -- > Andelf > BLOG:http://blog.sohu.com/members/andelf/ > BLOG:http://spaces.msn.com/members/andelf > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060226/5cc21bb3/attachment.htm
2006年02月26日 星期日 19:29
Tkinter.Button(root, text='aaa', command=click(arg)) 没点击按钮的时候就会先执行click(arg),然后把返回的对象传递给command。点击的时候就没有反应了。 On 2/26/06, Andelf <andelf at gmail.com> wrote: > > click(....)可以不? > > 在06-2-26,Gu Yingbo <tensiongyb at gmail.com> 写道: > > > > Tkinter.Button(root, text='aaa', command=click) > > 中的 command 怎么加入参数啊? > > > > _______________________________________________ > > python-chinese > > Post: send python-chinese at lists.python.cn > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > -- > Andelf > BLOG:http://blog.sohu.com/members/andelf/ > BLOG:http://spaces.msn.com/members/andelf > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060226/5d91a9a9/attachment.htm
2006年02月27日 星期一 14:19
On 2/26/06, Gu Yingbo <tensiongyb at gmail.com> wrote: > Tkinter.Button(root, text='aaa', command=click) > 中的 command 怎么加入参数啊? > 我认为,这里的那个click就像是一个函数指针,command=click相当于让command指向click,如果你写成command=click(...)就变成了command等于click(...)函数的返回值了. 问题是,你要加入什么参数呢?当按钮按下去之后就自然会调用click啊.没办法加入其它的参数呀. -- Best Regards, Leo Jay
2006年02月27日 星期一 18:35
Skipped content of type multipart/alternative-------------- next part -------------- """http://aspn.activestate.com/ASPN/Python/Cookbook/ The curry class used in this program is from Scott David Daniels' recipe "curry -- associating parameters with a function", available at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549 As in our discussion of lambda, I'm not going to try to explain how currying works. I'm simply going to treat the curry class as a black box. I won't talk much about how it works -- I'll only talk about how to work with it. CURRY -- HOW TO USE IT The way to use curry (the technique) is to include a "curry" class in your program, or to import it from its own Python file. In this program, we will include the curry code directly in the program. Originally, we thought that the following statement could bind self.buttonHandler to self.button1's command option, but we found out that it didn't work the way we thought it would. self.button1 = Button(self.myContainer1, command = self.buttonHandler(button_name, 1, "Good stuff!")) Using curry, the way to do what we want is to re-write this statement this way: self.button1 = Button(self.myContainer1, command = curry(self.buttonHandler, button_name, 1, "Good stuff!")) As you can see, the code is quite straightforward. Instead of invoking the self.buttonHandler function, we create a curry object (that is, an instance of the curry class), passing the self.buttonHandler function in as the first argument. Basically, what happens is that the curry object remembers the name of the function that it was given. Then when it (the curry object) is called, it -- in its own turn -- calls the function that it was given when it was created. EVENT BINDING Chad Netzer has devised a technique similar to currying, that can be used to parameterize event binding. [NOTE that this coding of the technique requires Python 2 or greater.] It involves using an "event_lambda" function. To use event_lambda, as with curry, you need to include the code for the "event_lambda" function in your program, or to import it from its own Python file. In this program, we include the code for the event_lambda function directly in our program. # ---------- code for function: event_lambda -------- def event_lambda(f, *args, **kwds ): "A helper function that wraps lambda in a prettier interface." return lambda event, f=f, args=args, kwds=kwds : f( *args, **kwds ) Once the event_lambda function is available to us, we can use it to bind self.buttonHandler to the keyboard event, and pass it some arguments. Here's how we do it: self.button1.bind(" ", event_lambda( self.buttonHandler, button_name, 1, "Good stuff!" ) ) If you have an absolutely insatiable curiosity about how event_lambda works, it is a little bit easier to see by looking at the coding for button2. For button2, use use a two-step process. First we invoke the event_lambda function. event_handler = event_lambda( self.buttonHandler, button_name, 2, "Bad stuff!" ) When the event_lambda function is called, it uses lambda to create a new, un-named ("anonymous") function object. lambda event, f=f, args=args, kwds=kwds : f( *args, **kwds ) The un-named function object is a wrapper for the function we really want to invoke ("f", which in this program is "self.buttonHandler") and the arguments we specified at the time we called the event_lambda function. Then the event_lambda function returns this new anonymous function. When event_lambda returns the anonymous function, we give it a name: "event_handler". event_handler = event_lambda( self.buttonHandler, button_name, 2, "Bad stuff!" ) Then, in the second step, we bind the event to the "event_handler" function. self.button2.bind(" ", event_handler ) Note that for the anonymous function, 'event' is just a placeholder argument which is discarded and never used. Only the positional arguments (args) and the keyword arguments (kwds) are passed to the button-handler routine. WOW! I JUST BURNED OUT A BUNCH OF BRAIN CELLS!! This is tricky stuff. But don't think that you need to burn out a bunch of brain cells trying to understand how it all works. You don't need to know HOW "curry" and "event_lambda" work in order to use them. Just treat them like black boxes... just use them and don't worry about how they work. LAMBDA VS. CURRY AND EVENT_LAMBDA -- WHICH SHOULD I USE? Well... * Code to invoke curry and event_lambda is relatively intuitive, short and simple. The downside is that using them requires you to include them in the code for your program, or to import them. * Lambda, in contrast, is built into the Python language -- you don't need to do anything special to import it; it is simply there. The downside is that the code to use it can be long and a bit confusing. So the choice is up to you. "You pays yer money and takes yer choice," as they say. Use what you are most comfortable with, and/or what seems most appropriate to the task. The REAL moral of this story is this... Python is a powerful language, and it provides many tools that can be used to create callback functions for handling events. "Thinking in Tkinter" is an introduction to basic concepts, not an encyclopedia of techniques, so we can explore only a few of those ways here. But you can be confident that as you become more skilled with Python, and as your need for more flexibility grows, there are more advanced features of Python that will be available to you, and that can enable you to create just the kind of callback function that you need. PROGRAM BEHAVIOR If you run this program, it will behave exactly as the previous program did. We haven't changed any of the behavior of the program, just the way the program is coded. [revised: 2003-02-23] >""" from Tkinter import * # ---------- code for class: curry (begin) --------------------- class curry: """from Scott David Daniels'recipe "curry -- associating parameters with a function" in the "Python Cookbook" http://aspn.activestate.com/ASPN/Python/Cookbook/ """ def __init__(self, fun, *args, **kwargs): self.fun = fun self.pending = args[:] self.kwargs = kwargs.copy() def __call__(self, *args, **kwargs): if kwargs and self.kwargs: kw = self.kwargs.copy() kw.update(kwargs) else: kw = kwargs or self.kwargs return self.fun(*(self.pending + args), **kw) # ---------- code for class: curry (end) --------------------- # ---------- code for function: event_lambda (begin) -------- def event_lambda(f, *args, **kwds ): """A helper function that wraps lambda in a prettier interface. Thanks to Chad Netzer for the code.""" return lambda event, f=f, args=args, kwds=kwds : f( *args, **kwds ) # ---------- code for function: event_lambda (end) ----------- class MyApp: def __init__(self, parent): self.myParent = parent self.myContainer1 = Frame(parent) self.myContainer1.pack() button_name = "OK" # command binding -- using curry self.button1 = Button(self.myContainer1, command = curry(self.buttonHandler, button_name, 1, "Good stuff!")) # event binding -- using the event_lambda helper function self.button1.bind(" ", event_lambda( self.buttonHandler, button_name, 1, "Good stuff!" ) ) self.button1.configure(text=button_name, background="green") self.button1.pack(side=LEFT) self.button1.focus_force() # Put keyboard focus on button1 button_name = "Cancel" # command binding -- using curry self.button2 = Button(self.myContainer1, command = curry(self.buttonHandler, button_name, 2, "Bad stuff!")) # event binding -- using the event_lambda helper function in two steps event_handler = event_lambda( self.buttonHandler, button_name, 2, "Bad stuff!" ) self.button2.bind(" ", event_handler ) self.button2.configure(text=button_name, background="red") self.button2.pack(side=LEFT) def buttonHandler(self, argument1, argument2, argument3): print " buttonHandler routine received arguments:", \ argument1.ljust(8), argument2, argument3 def buttonHandler_a(self, event, argument1, argument2, argument3): print "buttonHandler_a received event", event self.buttonHandler(argument1, argument2, argument3) print "\n"*100 # clear the screen print "Starting program tt079." root = Tk() myapp = MyApp(root) print "Ready to start executing the event loop." root.mainloop() print "Finished executing the event loop." -------------- next part -------------- """ * buttonHandler is a function object, and can be used as a callback binding. * buttonHandler() (note the parenthesis) on the other hand is an actual call to the "buttonHandler" function. At the time that the statement self.button1 = Button(self.myContainer1, command = self.buttonHandler(button_name, 1, "Good stuff!")) is executed, it is actually making a call to the "buttonHandler" routine. The buttonHandler routine executes, printing its message, and returns the results of the call (in this case, the None object). Then the button's "command" option is bound to the results of the call. In short, the command is bound to the "None" object. And that is why, when you click on either of the buttons, nothing happens. IS THERE A SOLUTION? So... what's the solution? Is there any way to parameterize, and reuse, an event-handler function? Yes. There are a couple of generally recognized techniques for doing this. One uses the Python built-in "lambda" function, and the other uses a technique called "currying". In this program we will discuss how to work with lambda, and in the next program we will look at currying. I'm not going to try to explain how lambda and currying work -- it is too complicated and too far off-track from our main goal, which is to get Tkinter programs working. So I'm going to simply treat them as black boxes. I won't talk about how they work -- I'll only talk about how to work with them. So let's look at lambda. COMMAND BINDING Originally, we thought the following statement might work: self.button1 = Button(self.myContainer1, command = self.buttonHandler(button_name, 1, "Good stuff!") ) ... but we found out that it didn't work the way we thought it would. The way to do what we want is to re-write this statement this way: self.button1 = Button(self.myContainer1, command = lambda arg1=button_name, arg2=1, arg3="Good stuff!" : self.buttonHandler(arg1, arg2, arg3) ) EVENT BINDING Happily, lambda also gives us a way to parameterize event binding. Instead of: self.button1.bind(" ", self.buttonHandler_a(event, button_name, 1, "Good stuff!")) (which wouldn't work, because there was no way to include the event argument in the argument list), we can use lambda, this way: # event binding -- passing the event as an argument self.button1.bind(" ", lambda event, arg1=button_name, arg2=1, arg3="Good stuff!" : self.buttonHandler_a(event, arg1, arg2, arg3) ) [Note that "event" here is a variable name -- it is not a Python keyword or anything like that. This example uses the name "event" for the event argument, but some discussions of this technique use the name "e" for the event argument, and we could just as easily have called it "event_arg" if we had wanted to.] One of the nice features of using lambda is that we can (if we wish), simply not pass the event argument. If we don't pass the event argument, then we can call the self.buttonHandler function directly, instead of indirectly through the self.buttonHandler_a function. To illustrate this technique, we will code the event binding for button2 differently than we did for button1. This is what we do with button2: # event binding -- without passing the event as an argument self.button2.bind(" ", lambda event, arg1=button_name, arg2=2, arg3="Bad stuff!" : self.buttonHandler(arg1, arg2, arg3) ) PROGRAM BEHAVIOR If you run this program, it will behave just as we wish. Note that you can change the keyboard focus from the OK to the CANCEL button, and back again, by pressing the TAB key on the keyboard. In particular, you should experiment with invoking the OK button by pressing the key on the keyboard. If you invoke the OK button via a keypress of the key, you will be going through the buttonHandler_a function, and you will also get a message from it, printing information about the event that has been passed to it. In any case, whether you click on one of the button widgets with the mouse, or invoke a widget via a keypress on the keyboard, it will nicely print the arguments that were passed to the buttonHandler function. [revised: 2003-02-23] >""" from Tkinter import * class MyApp: def __init__(self, parent): self.myParent = parent self.myContainer1 = Frame(parent) self.myContainer1.pack() #------------------ BUTTON #1 ------------------------------------ button_name = "OK" # command binding self.button1 = Button(self.myContainer1, command = lambda arg1=button_name, arg2=1, arg3="Good stuff!" : self.buttonHandler(arg1, arg2, arg3) ) # event binding -- passing the event as an argument self.button1.bind(" ", lambda event, arg1=button_name, arg2=1, arg3="Good stuff!" : self.buttonHandler_a(event, arg1, arg2, arg3) ) self.button1.configure(text=button_name, background="green") self.button1.pack(side=LEFT) self.button1.focus_force() # Put keyboard focus on button1 #------------------ BUTTON #2 ------------------------------------ button_name = "Cancel" # command binding self.button2 = Button(self.myContainer1, command = lambda arg1=button_name, arg2=2, arg3="Bad stuff!": self.buttonHandler(arg1, arg2, arg3) ) # event binding -- without passing the event as an argument self.button2.bind(" ", lambda event, arg1=button_name, arg2=2, arg3="Bad stuff!" : self.buttonHandler(arg1, arg2, arg3) ) self.button2.configure(text=button_name, background="red") self.button2.pack(side=LEFT) def buttonHandler(self, argument1, argument2, argument3): print " buttonHandler routine received arguments:" \ , argument1.ljust(8), argument2, argument3 def buttonHandler_a(self, event, argument1, argument2, argument3): print "buttonHandler_a received event", event self.buttonHandler(argument1, argument2, argument3) print "\n"*100 # clear the screen print "Starting program tt078." root = Tk() myapp = MyApp(root) print "Ready to start executing the event loop." root.mainloop() print "Finished executing the event loop."
2006年02月27日 星期一 19:41
On 2/27/06, Leo Jay <python.leojay at gmail.com> wrote: > > On 2/26/06, Gu Yingbo <tensiongyb at gmail.com> wrote: > > Tkinter.Button(root, text='aaa', command=click) > > 中的 command 怎么加入参数啊? > > > > > 我认为,这里的那个click就像是一个函数指针,command=click相当于让command指向click,如果你写成command=click(...)就变成了command等于click(...)函数的返回值了. 实际情况确实是这样的。 问题是,你要加入什么参数呢?当按钮按下去之后就自然会调用click啊.没办法加入其它的参数呀. 因为我写的 click 函数是带参数的呀(我的多个按钮是用一个 for 循环产生的,点击每个按钮效果肯定要不一样嘛,所以要带参数。) -- > Best Regards, > Leo Jay > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060227/0ba0d498/attachment.htm
2006年02月27日 星期一 19:55
谢谢!例子里面用的是lambda的方法,这样就行了: Tkinter.Button(root, text='aaa', command=lambda arg1=my_arg:click(arg1)) 这个方法挺好,自己可以添加任意的参数了。 今天才知道lambda 匿名函数可以带参数,谢谢! On 2/27/06, tcgy2004 <tcgy2004 at tom.com> wrote: > > 因该能实现的,你可以参考think in tkinter. > 附件是thinker in tkinter中一部分,说的就是相关的内容! > > > ----- Original Message ----- > *From:* Gu Yingbo <tensiongyb at gmail.com> > *To:* python-chinese at lists.python.cn > *Sent:* Sunday, February 26, 2006 7:29 PM > *Subject:* Re: [python-chinese] 请教一个问题 > > Tkinter.Button(root, text='aaa', command=click(arg)) > 没点击按钮的时候就会先执行click(arg),然后把返回的对象传递给command。点击的时候就没有反应了。 > > On 2/26/06, Andelf <andelf at gmail.com> wrote: > > > > click(....)可以不? > > > > 在06-2-26,Gu Yingbo <tensiongyb at gmail.com> 写道: > > > > > > Tkinter.Button(root, text='aaa', command=click) > > > 中的 command 怎么加入参数啊? > > > > > > _______________________________________________ > > > python-chinese > > > Post: send python-chinese at lists.python.cn > > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > > > > > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > > > > > > > > -- > > Andelf > > BLOG:http://blog.sohu.com/members/andelf/ > > BLOG: http://spaces.msn.com/members/andelf > > _______________________________________________ > > python-chinese > > Post: send python-chinese at lists.python.cn > > Subscribe: send subscribe to python-chinese-request at lists.python.cn > > Unsubscribe: send unsubscribe to > > python-chinese-request at lists.python.cn > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > > > ------------------------------ > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request at lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060227/5ca2bf70/attachment.html
2006年02月28日 星期二 21:04
长见识啊,lambda真是好东西
Zeuux © 2025
京ICP备05028076号