Phill
Phill

Reputation: 545

Python tkinter passing input value within the same class

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()
        

Upvotes: 2

Views: 869

Answers (2)

IronManMark20
IronManMark20

Reputation: 1338

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()

Upvotes: 1

Bryan Oakley
Bryan Oakley

Reputation: 385820

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.

Upvotes: 2

Related Questions