0

NameError: name 'onOpen' is not defined

There is something wrong with the command function. I am not sure what I did wrong here. I had the code tested before the onOpen function and it works fine.

    import tkinter as tk
from tkinter import filedialog

class Application(tk.Frame): 
    def __init__(self, master=None):
        tk.Frame.__init__(self, master) 
        self.pack() 
        self.createWidgets()

    def onOpen():
        """ Ask the user to choose a file and update the values of label change button"""
        button_label.set(filedialog.askopenfilename(filetypes = ()))

    def createWidgets(self):

        #instruction label
        self.labelInstruct = tk.Label(self, text="Instructions:", padx=10, pady=10)
        self.labelInstruct = tk.Label(self, text="All you have to do is insert the file and save it.\n The conversion is instant", padx=10, pady=10)
        self.labelInstruct.pack()

        #insertfile button
        self.ifbut = tk.Button(self, text="Insert File", command=onOpen)
        self.ifbut.pack()

        button_label = tk.StringVar(self)
        text = tk.Label(self, textvariable = button_label)
        text.pack()

        #save button
        self.saveLabel = tk.Label(self, text="Save File", padx=10, pady=10)
        self.saveLabel.pack()
        self.saveButton = tk.Button(self)
        self.saveButton.pack()

        #quit button
        self.quitButton = tk.Button(self, text='Quit',
            command=self.quit) 
        self.quitButton.pack()

app = Application() 
app.master.title('Sample application') 
app.mainloop()
B Hok
  • 145
  • 1
  • 6
  • 15

2 Answers2

2

Seeing that there are many problems with the way this code is written I am only going to point out a few of them and tackle the main question from the OP.

Lets start with the fact that you need to define the main window with something like root = tk.Tk() and you also need to make sure all your methods in your class have the argument self as the first argument.

Also any variable you are defining also should have self so that the class can interact with it. This (button_label) for example should be self.button_label.

There is no reason to use return the way you are trying to in the onOpen(self): method. Return does not work like that. Return is there so you can return a value to something that is calling the function/method to be used for something else and is not for setting the value of something.

Note that I also add the root window variable to the app = Application(root) line. This lets us pass the main window into the class.

all and all the following should work for the onOpen(self): function but the rest still needs some work.

import tkinter as tk
from tkinter import filedialog


class Application(tk.Frame): 
    def __init__(self, parent):
        tk.Frame.__init__(self, parent) 
        self.parent = parent
        self.pack() 
        self.createWidgets()

    def onOpen(self):
        """ Ask the user to choose a file and update the values of label change button"""
        self.button_label.set(filedialog.askopenfilename(filetypes = ()))

    def createWidgets(self):

        #instruction label
        self.labelInstruct = tk.Label(self.parent, text="Instructions:", padx=10, pady=10)
        self.labelInstruct = tk.Label(self.parent, text="All you have to do is insert the file and save it.\n The conversion is instant", padx=10, pady=10)
        self.labelInstruct.pack()

        #insert file button
        self.ifbut = tk.Button(self.parent, text="Insert File", command = self.onOpen)
        self.ifbut.pack()

        self.button_label = tk.StringVar()
        self.text = tk.Label(self.parent, textvariable = self.button_label)
        self.text.pack()

        #save button
        self.saveLabel = tk.Label(self.parent, text="Save File", padx=10, pady=10)
        self.saveLabel.pack()
        self.saveButton = tk.Button(self.parent, text = "Save")
        self.saveButton.pack()

        #quit button
        self.quitButton = tk.Button(self.parent, text='Quit', command=self.quit) 
        self.quitButton.pack()


root = tk.Tk()
app = Application(root) 
app.master.title('Sample application') 
app.mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
-1

You need to return the function value as below:

def onOpen():
    """ Ask the user to choose a file and update the values of label change button"""
    return button_label.set(filedialog.askopenfilename(filetypes = ()))    
dildeolupbiten
  • 1,314
  • 1
  • 15
  • 27
  • 1
    There’s many issues in the OP’s code, that’s not one of them. You **do not** return `tkinter.label.set()` – Taku Jun 10 '17 at 01:10
  • Guess, i gave a wrong suggestion. What is the correct recommendation? – dildeolupbiten Jun 10 '17 at 01:20
  • Since there’s so many problems, I would rather flag this question as Too Broad. But.... Just dealing with the NameError, the `command` argument should be changed to `command=self.onOpen` since `onOpen` is an instance method. And that because it’s an instance method, the `onOpen` should accept the `self` arg. `def onOpen(self):`. There will still some errors left for the OP to figure out themself. – Taku Jun 10 '17 at 01:31
  • And the reason why your solution is wrong because `.set()` is an inplace method. Adding a return statement’s just making it return None. Just like how you don’t do this: `return list.append()` – Taku Jun 10 '17 at 01:33
  • Yes, i agree with what you said. Since onOpen is an instance method, the function should be written def onOpen(self) and command parameter should be self.onOpen. Thanks for your attention. Guess i made a comment on a topic that i haven't known well yet. – dildeolupbiten Jun 10 '17 at 01:44
  • But i want to show you an example about returning a function. Please look at this page. An author returned a function. See the Jonathan Reinharts post. https://stackoverflow.com/questions/7674790/bundling-data-files-with-pyinstaller-onefile/44352931#44352931 Is this case different than this? – dildeolupbiten Jun 10 '17 at 01:52
  • I think you’ll need to review the difference between returning an in-place operation (some function hat doesn’t return anything) and returning a returned result. `.set()` is an in-place operation while your linked answer `os.path.join()` returns a result (path string). **It’s absolutely not a good practice to return an in-place operation.** – Taku Jun 10 '17 at 04:19
  • Yes, you are right, and i appreciate you showing me one of the places I should review. – dildeolupbiten Jun 10 '17 at 10:29