2

This is a pretty general question about the optionmenu widget in tkinter.

When defining an OptionMenu widget, and assigning a function as its command, why does it require an argument?

My code:

from tkinter import *

def update():
    x = optionvar.get()
    x = str(x)
    mylabel.config(text=x)

root = Tk()

l = []
for n in range(10):
    l.append(n)

t = tuple(l)

optionvar = IntVar()

optionvar.set('hello stackoverflow')

mymenu  = OptionMenu(root, optionvar, *t, command=update)
mylabel = Label(root)

mymenu.pack()
mylabel.pack()

My errors:

TypeError: update() takes 0 positional arguments but 1 was given

Simply defining update with

def update(foo):

seems to work. But why?

Pax Vobiscum
  • 2,551
  • 2
  • 21
  • 32

1 Answers1

5

The callback usually wants to know which item was selected, so the value of the IntVar is passed as an argument. If you want to ignore that argument, you can simply use a lambda (_ is a valid name that is commonly used to indicate that it is a throwaway variable):

mymenu = OptionMenu(root, optionvar, *t, command=lambda _: update())
zondo
  • 19,901
  • 8
  • 44
  • 83
  • Thank you! Was going to have a hard time explaining to my teacher why I passed an unused variable... – Pax Vobiscum Mar 13 '16 at 18:47
  • Say if I wanted to use this functionality for a button instead, how could I pass the button itself as an argument (a calculator for example)? – Pax Vobiscum Mar 13 '16 at 20:16
  • [Here](http://stackoverflow.com/a/16114318/5827958) is an answer that tells you how to do just that. – zondo Mar 13 '16 at 20:23
  • What you say about how it works is incorrect: It doesn't pass the `OptionMenu` instance to the function as an argument, it passes the _value_ associated with the menu item that was selected (an `int` in this case). – martineau Aug 13 '17 at 13:41
  • 1
    @martineau: I can't believe I went so far as to post an answer without testing. I stand corrected. – zondo Aug 13 '17 at 13:49
  • That's better. Having it pass the `OptionMenu` instance could be useful if, say, you had a bunch of menu widgets, and in cases like that the `lambda` could be used to pass additional arguments when calling the actual target function. – martineau Aug 13 '17 at 14:01