-1

I'm beginning to write a GUI, based on the code included at the following site: effbot.org/tkinterbook/menu.htm.

Ideally, every time I would click one of the commands on the sample rate cascade, as shown in the image, 2, the freq variable would be updated, and its value printed to the terminal using the freqflag function. Instead, it seems that when I run the code, the freqflag function is called each time a command on the "sample rate" cascade is initialised.

from Tkinter import *
import ttk
root = Tk()
def hello():
    print 'hello'
def freqflag(freq):
    print "frequency = %3.5f kHz" %(freq) 
freq = 0
freqs = [1, 2, 3, 4]
content = ttk.Frame(root)
content.grid(column=0, row=0)
frame = ttk.Frame(content, borderwidth=5, relief="sunken")
menubar =  Menu(root)           
menubar.add_command(label = "Hello", command=hello)
menubar.add_command(label = "Quit", command=root.quit)
freqmenu = Menu(menubar, tearoff=0) #here, the menubar is parent
for freq in freqs:
    freqmenu.add_command(label=str(freqs[freq-1]), command=freqflag(freqs[freq-1]))
menubar.add_cascade(label = "sample rate", menu = freqmenu)
root.config(menu=menubar)
root.mainloop()

Resulting GUI

What I find particularly strange is that the initialization of the "Hello" and "Quit" commands do not call the hello() function, or cause the root GUI to exit, respectively. I'm using python 2.7.

Any suggestions on what I might be doing wrong here are welcome.

tcronin
  • 11
  • 1

1 Answers1

2

When you write:

freqmenu.add_command(label=str(freqs[freq-1]), command=freqflag(freqs[freq-1]))

The results of str() and freqflag() are assigned to label and command. If you want command to be binded to a method (and not the result), you have to make a closure (a method that returns a method) or a lambda expression.

Lambda

freqmenu.add_command(..., command=lambda: freqflag(freqs[freq-1]))

Closure

def freqflag(freq):
    def inner():
        print "frequency = %3.5f kHz" %(freq)
    return inner
freqmenu.add_command(..., command=freqflag(freqs[freq-1]))
romain-aga
  • 1,441
  • 9
  • 14
  • **Lambda** solves the problem defined in the initial post but leaves the variable freq set to 4. I didn't find this useful subsequently as clicking on any option under `sample rate` results in the same `frequency=4kHz`message. **Closure** works perfectly here. – tcronin Jun 10 '17 at 20:36