Question

I'm trying to write a function to open a recent file when it's selected from a submenu, but when I loop through the recent files the last file is the only one that is recognized.

Here's a sample bit of code to illustrate the issue:

from Tkinter import *

class App(Frame):
    def __init__(self, root):
        Frame.__init__(self, root)
        menubar = Menu(self, tearoff=0)
        fileMenu = Menu(self, tearoff=0)
        recentMenu = Menu(self, tearoff=0)

        menubar.add_cascade(label="File", menu=fileMenu)
        fileMenu.add_cascade(label="Open Recent", menu=recentMenu)
        for name in ('file1.txt', 'file2.txt', 'file3.txt'):
            recentMenu.add_command(label=name, command=lambda: self.load_file(name))

        root.configure(menu=menubar)
        root.geometry("200x200")

    def load_file(self, f):
        print f

if __name__ == "__main__":
    root = Tk()
    App(root).pack(fill="both", expand=True)
    root.mainloop()

When I click on file2.txt for example, the program outputs file3.txt instead. I'm sure I'm missing something trivial, but I can't figure out what that is.

Was it helpful?

Solution

the following works:

...

    for name in ('file1.txt', 'file2.txt', 'file3.txt'):
        recentMenu.add_command(label=name, command=self.load_file(name))

...

def load_file(self, f):
    def fun():
        print f
    return fun

In your version, at the moment, when you call the callback function, name refers to the instance file3.txt. In my version, the instances file1.txt, file2,txt, and so on, are captured inside closures (not strictly a closure, but very similar).

See closures in SO.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top