[Patches] Tkinter OptionMenu callback

Barry A. Warsaw bwarsaw@cnri.reston.va.us (Barry A. Warsaw)
Thu, 24 Feb 2000 15:13:03 -0500 (EST)


On 02-Apr-1999, Randal Hooper posted a question to the python-list
about hooking a callback into a Tkinter OptionMenu, so that when some
choice is selected, the callback is called.  I've found that we need
the same functionality.

In this URL, Randall posts his patch:

    http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=462053022

I've slightly modified this so that the callback gets the value as the
first argument; here's an example usage:

-------------------- snip snip --------------------
from Tkinter import *
import sys

def quit(value, args=None):
    if value == 'quit':
        sys.exit(0)

tk = Tk()
svar = StringVar()
svar.set('5x')
f = Frame(tk)
om = OptionMenu(f, svar, '5x', '10x', '20x', 'quit', command=quit)
om.pack()
f.pack()

tk.mainloop()
-------------------- snip snip --------------------

And here is my version of Randall's patch.  What say ye, Tkinter
experts?

-Barry

Index: Tkinter.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/lib-tk/Tkinter.py,v
retrieving revision 1.134
diff -c -r1.134 Tkinter.py
*** Tkinter.py	1999/10/20 12:29:56	1.134
--- Tkinter.py	2000/02/24 20:07:13
***************
*** 1790,1813 ****
  		self.tk.call((self._w, 'yview', '-pickplace') + what)
  
  class _setit:
! 	def __init__(self, var, value):
  		self.__value = value
  		self.__var = var
  	def __call__(self, *args):
  		self.__var.set(self.__value)
  
  class OptionMenu(Menubutton):
! 	def __init__(self, master, variable, value, *values):
! 		kw = {"borderwidth": 2, "textvariable": variable,
! 		      "indicatoron": 1, "relief": RAISED, "anchor": "c",
! 		      "highlightthickness": 2}
! 		Widget.__init__(self, master, "menubutton", kw)
  		self.widgetName = 'tk_optionMenu'
  		menu = self.__menu = Menu(self, name="menu", tearoff=0)
  		self.menuname = menu._w
! 		menu.add_command(label=value, command=_setit(variable, value))
  		for v in values:
! 			menu.add_command(label=v, command=_setit(variable, v))
  		self["menu"] = menu
  
  	def __getitem__(self, name):
--- 1790,1819 ----
  		self.tk.call((self._w, 'yview', '-pickplace') + what)
  
  class _setit:
! 	def __init__(self, var, value, callback=None):
  		self.__value = value
  		self.__var = var
+ 		self.__callback = callback
  	def __call__(self, *args):
+ 		if self.__callback:
+ 			apply(self.__callback, (self.__value,)+args)
  		self.__var.set(self.__value)
  
  class OptionMenu(Menubutton):
! 	def __init__(self, master, variable, value, *values, **kw):
! 		basekw = {"borderwidth": 2, "textvariable": variable,
! 			  "indicatoron": 1, "relief": RAISED, "anchor": "c",
! 			  "highlightthickness": 2}
! 		Widget.__init__(self, master, "menubutton", basekw)
  		self.widgetName = 'tk_optionMenu'
  		menu = self.__menu = Menu(self, name="menu", tearoff=0)
  		self.menuname = menu._w
! 		callback = kw.get('command')
! 		menu.add_command(label=value,
! 				 command=_setit(variable, value, callback))
  		for v in values:
! 			menu.add_command(label=v,
! 					 command=_setit(variable, v, callback))
  		self["menu"] = menu
  
  	def __getitem__(self, name):