2

Most of the code below is just so the problem is accurately replicated, the issue most likely is in the hand-off of filename fromaskopenfilenameI() to printing(stringToPrint)or the if statement at the end.

Goal

The goal of this program is to simply print the file path to the console when Print File Path button is clicked.

Current state

When the program is executed the window appears correctly and the it lets you select a file in the file system. Once the file is opened, the script seems to call printing method before it executes its own print statement. When I open another file it prints the only the print statement from askopenfilename() (which is correct).

However, clicking the Print File Path Button does not seem to get work at any stage.

An example output would be:

Value on click: no-file

askopenfilename value: C:/Temp/AFTER_FIRST_OPEN.txt

askopenfilename value: C:/Temp/AFTER_SECOND_OPEN.txt

Code

import Tkinter, Tkconstants, tkFileDialog

filename = 'no-file'

class TkApp(Tkinter.Frame):

    def __init__(self, root):

        Tkinter.Frame.__init__(self, root)
    
        # options for buttons
        button_opt = {'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5}
    
        # define buttons
        Tkinter.Button(self, text='Open File', command=self.askopenfilename).pack(**button_opt)
        Tkinter.Button(self, text='Print File Path', command=self.printing(filename)).pack(**button_opt)
        Tkinter.Button(self, text='Quit', command=self.quit).pack(**button_opt)
         
        # define options for opening or saving a file
        self.file_opt = options = {}
        options['defaultextension'] = '.twb'
        options['filetypes'] = [('All', '*')]
        options['initialdir'] = 'C:\\'
        options['parent'] = root
        options['title'] = 'Select a File'

    def askopenfilename(self):
        """Returns an opened file in read mode.
        This time the dialog just returns a filename and the file is opened by your own code.
        """
        global filename        
        # get filename
        filename = tkFileDialog.askopenfilename(**self.file_opt)
    
        # open file on your own
        if filename:
            print "askopenfilename value: " + filename
            return filename
            
    def printing(self, stringToPrint):
        print "Value on click: " + stringToPrint
   
    def quit(self):
        root.destroy()
        
 if __name__=='__main__':
        root = Tkinter.Tk()
        root.title("Path Printer")  
        TkApp(root).pack()
        root.mainloop()
        
1
  • The command=self.printing(filename) argument is actually calling the printing() function as the "Print File Path" Button is being defined. Commented May 8, 2015 at 21:18

2 Answers 2

2

The root of your problem is that you're calling self.printing at the time you create the button. The solution is simple: change self.printing(filename) to be just self.printing, and then have self.printing print an attribute that is set by self.askopenfilename.

For example:

class TkApp(Tkinter.Frame):
    def __init__(self, root):
        ...
        self.currentFile = None
        ...
        Tkinter.Button(self, text='Open File', command=self.askopenfilename)
        Tkinter.Button(self, text='Print File Path', command=self.printing)
        ...

    def askopenfilename(self):
        ...
        self.currentFile = tkFileDialog.askopenfilename(**self.file_opt)
        ...

    def printing(self):
        print "Value on click: " + self.currentFile

Note: a return statement in a function that is called from a button serves absolutely no purpose. The actual caller of the button ignores all return values.

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

1 Comment

Thanks a ton Bryan! So just to understand this for next time, the function does not have to "return" a value in order to be picked up by another function? Is it enough to define a variable?
1

I think the problem is that the self.printing function cannot take arguments when called from a button press. This is common in many GUI libraries. To get around this, I would recommend that you change filename to self.filename, so that it can be called from self.printing even if it isn't passed.

The code would be:

import Tkinter, Tkconstants, tkFileDialog
class TkApp(Tkinter.Frame):
    def __init__(self, root):
        Tkinter.Frame.__init__(self, root)
        # options for buttons
        button_opt = {'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5}
        #moved initiation of filename to here so it will print if no file has been selected
        self.filename = 'no-file'
        # define buttons
        Tkinter.Button(self, text='Open File', command=self.askopenfilename).pack(**button_opt)
        Tkinter.Button(self, text='Print File Path', command=self.printing).pack(**button_opt) #not the removal of variable.
        Tkinter.Button(self, text='Quit', command=self.quit).pack(**button_opt)

        # define options for opening or saving a file
        self.file_opt = options = {}
        options['defaultextension'] = '.twb'
        options['filetypes'] = [('All', '*')]
        options['initialdir'] = 'C:\\'
        options['parent'] = root
        options['title'] = 'Select a File'

    def askopenfilename(self):
        """Returns an opened file in read mode.
        This time the dialog just returns a filename and the file is opened by your own code.
        """       
        # get filename - edited to be part of self
        self.filename = tkFileDialog.askopenfilename(**self.file_opt)

        # open file on your own
        if self.filename:
            print "askopenfilename value: " + self.filename
            return self.filename

    def printing(self):
        print "Value on click: " + self.filename

    def quit(self):
        root.destroy()

if __name__=='__main__':
        root = Tkinter.Tk()
        root.title("Path Printer")  
        TkApp(root).pack()
        root.mainloop()

Comments

Your Answer

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.