Tkinter Button Commands are Called Only at Startup?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Daniel M
    New Member
    • Feb 2012
    • 7

    Tkinter Button Commands are Called Only at Startup?

    I am trying to use Tkinter to build a simple GUI app which imports data and performs some analysis. The GUI has just four labels and four buttons side by side. When you press the button, you should get a File Dialog prompt. However, whenever I run the script (see below), Python calls all button commands at startup, and then the buttons don't work afterwards. Even if I write the code without a class, the same thing happens. How do I get it to stop doing this? Thanks!

    Code:
    import numpy
    import scipy
    
    from Tkinter import *
    import tkFileDialog as tkf
    
    filenames = {}
    
    class App:
        def __init__(self, master):
            
                frame = Frame(master)
                frame.pack()
                
                self.Name0 = Label(frame, text = "Initial Data", width=30).grid(row=0, sticky=W,columnspan=2)
                self.Name1 = Label(frame, text = "After Change #1", width=30).grid(row=1, sticky= W,columnspan=2)
                self.Name2 = Label(frame, text = "After Change #2", width=30).grid(row=2,sticky=W,columnspan=2)
                self.Name3 = Label(frame, text = "Current State", width=30).grid(row=3,sticky=W,columnspan=2)
    
                self.Butt0 = Button(frame, text = "Select", command=tkf.askopenfile()).grid(row=0,column=2)
                self.Butt1 = Button(frame, text = "Select", command=tkf.askopenfile()).grid(row=1,column=2)
                self.Butt2 = Button(frame, text = "Select", command=tkf.askopenfile()).grid(row=2,column=2)
                self.Butt3 = Button(frame, text = "Select", command=tkf.askopenfile()).grid(row=3,column=2)
    
    
    root = Tk()
    
    app = App(root)
    
    root.mainloop()
  • dwblas
    Recognized Expert Contributor
    • May 2008
    • 626

    #2
    Loose the parens in the command statement. Tkinter assumes that it is a function and so adds the parens itself.
    Code:
                 self.Butt0 = Button(frame, text = "Select", command=tkf.askopenfile).grid(row=0,column=2)
                 self.Butt1 = Button(frame, text = "Select", command=tkf.askopenfile).grid(row=1,column=2)
                 self.Butt2 = Button(frame, text = "Select", command=tkf.askopenfile).grid(row=2,column=2)
                 self.Butt3 = Button(frame, text = "Select", command=tkf.askopenfile).grid(row=3,column=2)
    But then, how do you store the file name selected? You should call a function, which calls askopenfile[name?] and stores the name selected. You can use the same function for all buttons and just send it the button number. Also, grid() returns None so there is no reason to save the button id's.
    Code:
    from Tkinter import *
    import tkFileDialog as tkf
    from functools import partial
     
    class App:
        def __init__(self, master):
     
                 frame = Frame(master)
                 frame.pack()
     
                 self.Name0 = Label(frame, text = "Initial Data", width=30).grid(row=0, sticky=W,columnspan=2)
                 self.Name1 = Label(frame, text = "After Change #1", width=30).grid(row=1, sticky= W,columnspan=2)
                 self.Name2 = Label(frame, text = "After Change #2", width=30).grid(row=2,sticky=W,columnspan=2)
                 self.Name3 = Label(frame, text = "Current State", width=30).grid(row=3,sticky=W,columnspan=2)
     
                 self.Butt0 = Button(frame, text = "Select", command=partial(self.get_file_name, 0)).grid(row=0,column=2)
                 print self.Butt0
                 Button(frame, text = "Select", command=partial(self.get_file_name, 1)).grid(row=1,column=2)
                 Button(frame, text = "Select", command=partial(self.get_file_name, 2)).grid(row=2,column=2)
                 Button(frame, text = "Select", command=partial(self.get_file_name, 3)).grid(row=3,column=2)
     
        def get_file_name(self, button_num):
            fname=tkf.askopenfilename()
            print "name for button %d is %s" % (button_num, fname)
    
    root = Tk()
     
    app = App(root)
     
    root.mainloop()

    Comment

    • Daniel M
      New Member
      • Feb 2012
      • 7

      #3
      Oh, wow, that totally worked. Yeah, I plan to store the file names, but I was just testing it. I still don't understand why the parenthesis would cause the call to the button commands immediately and then never again. Anyways, thanks a lot!

      Comment

      • dwblas
        Recognized Expert Contributor
        • May 2008
        • 626

        #4
        I still don't understand why the parenthesis would cause the call to the button commands
        That executes a call to the function and sets the command to the return value of the function, which you could do if you wanted, but I can't think of any reason why anyone would want to.

        Comment

        • bvdet
          Recognized Expert Specialist
          • Oct 2006
          • 2851

          #5
          You might want to pass a value to the function when the button is pushed. In that case you could use a lambda or closure. Lambda example:
          Code:
          command=lambda: tkf.askopenfile(file_name_variable1)

          Comment

          Working...