Skip to main content
  1. About
  2. For Teams
Asked
Viewed 1k times
2

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.

2
  • I guess you also see file3.txt, when clicking on file1.txt?
    spiehr
    –  spiehr
    2014-02-23 02:27:32 +00:00
    Commented Feb 23, 2014 at 2:27
  • @spiehr yep, it seems to always select the last item that's being iterated over in the for loop
    rhowe
    –  rhowe
    2014-02-23 02:35:07 +00:00
    Commented Feb 23, 2014 at 2:35

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

I found a solution where you can go through a list automatically:

for element in list:
    sub_menu.add_command(label=element, command=lambda f=element: addToPlaylist(str(f)))

Comments

Your Answer

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.