What are the limitations of callback functions related to Tkinter traces?

I am trying to figure out how to implement a callback function that does something more meaningful than just printing. I'm pretty inexperienced, so I'm not sure how callback functions should or can be implemented in Python (or any other language, for that matter).

Consider the following Python code:

from Tkinter import * def callbackfunc(*args): print "Hello World!" class App: def __init__(self, master): frame = Frame(master) frame.pack() optionvalue = IntVar(master) optionvalue.set(2) optionvalue.trace("w", callbackfunc) self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4) self.optionmenu.pack() 

I am trying to implement OptionMenu (Tkinter widget) in such a way that when changing its selected value, the callback function does something meaningful - more specifically, it will change the value of the global variable defined elsewhere in the program, since it is implemented above, it just prints the output (albeit successfully).

I cannot figure out how to pass parameters to my callback function. I do not want this callback function to return anything; however, I am curious how I will return my callback function, and how I will implement the rest of my program so that it can use those returned results, whatever they are. Am I trying to implement a Python callback function so that it is not implemented? If not, how do I get this to work?

+4
source share
3 answers

It's a bit unclear what you mean by "passing parameters to my callback function". You already do it! For instance:

 from Tkinter import * def callbackfunc(*args, **kwargs): print args, kwargs print "Hello World!" class App(object): def __init__(self, master): frame = Frame(master) frame.pack() optionvalue = IntVar(master) optionvalue.set(2) optionvalue.trace("w", callbackfunc) self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4) self.optionmenu.pack() root = Tk() app = App(root) root.mainloop() 

At startup ...

 $ python foo.py ('PY_VAR0', '', 'w') {} Hello World! 

So, you see, when Tkinter calls your callback, it passes parameters to it. If you want to do something other than print them, you can save them in some state by passing a method instead of a function.

 from Tkinter import * class App(object): def __init__(self, master): frame = Frame(master) frame.pack() optionvalue = IntVar(master) optionvalue.set(2) optionvalue.trace("w", self.callbackfunc) self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4) self.optionmenu.pack() self.state = [] def callbackfunc(self, *args): self.state.append(args) print self.state root = Tk() app = App(root) root.mainloop() 

At startup ...

 $ python foo.py [('PY_VAR0', '', 'w')] [('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w')] [('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w')] 

Also, maybe you want to access the value of optionvalue . Then you can save a link to it:

 from Tkinter import * class App(object): def __init__(self, master): frame = Frame(master) frame.pack() self.optionvalue = IntVar(master) self.optionvalue.set(2) self.optionvalue.trace("w", self.callbackfunc) self.optionmenu = OptionMenu(master, self.optionvalue, 1, 2, 3, 4) self.optionmenu.pack() self.state = [] def callbackfunc(self, *args): self.state.append(args) print self.state print self.optionvalue.get() root = Tk() app = App(root) root.mainloop() 

At startup ...

 $ python foo.py [('PY_VAR0', '', 'w')] 1 [('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w')] 2 [('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w')] 3 

You can also use root.getvar(name) with name = 'PY_VAR0' (the first argument passed to the callback), as noob oddy suggests.

+4
source

If you want to send an extra argument - or just the arguments of your choice - you can use lambda. Some people find lambda confusing, but it can be a powerful tool.

specify your callback, but you want:

 def callbackfunc(message=None): print message 

use lambda to accept the arguments passed to Tkinter and the keyword arguments for any additional arguments you want to send, then call your callback with any of those arguments you want. For instance:

  optionvalue.trace("w", lambda name, index, op, message="hello, world": callbackfunc(message)) 

You can also use functools.partial to do the same in syntax, which might be easier to read.

+2
source
 from Tkinter import * def callbackfunc(name, index, mode): print root.getvar(name) class App: def __init__(self, master): frame = Frame(master) frame.pack() optionvalue = IntVar(master) optionvalue.set(2) optionvalue.trace("w", callbackfunc) self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4) self.optionmenu.pack() root = Tk() app = App(root) root.mainloop() 
+1
source

Source: https://habr.com/ru/post/1403382/


All Articles