Longroadahead
Longroadahead

Reputation: 381

Tkinter button store return value as variable

I have two button to store the path of opened file but I feel this process is duplicating code and uses global. I'm wondering if there is a way to do a return in the function and store that return value in a variable.

Here is my current code

browsebutton = Button(root, text="This Week's Report", command=getFilecurrent)
browsebutton.grid(row=0, column=0)

browsebutton2 = Button(root, text="Last Week's Report", command=getFilepast)
browsebutton2.grid(row=0, column=1)

def getFilecurrent():
    global path
    # open dialog box to select file
    path = filedialog.askopenfilename(initialdir="/", title="Select file")


def getFilepast():
    global pathpast
    # open dialog box to select file
    pathpast = filedialog.askopenfilename(initialdir="/", title="Select file")

Ideally I was thinking doing something like this

def getFilepath():
        # open dialog box to select file
        path = filedialog.askopenfilename(initialdir="/", title="Select file")
        return path

and somehow store the return path to a variable. This way, I will only need one path storing function and will not have to use global variables.

Upvotes: 1

Views: 2085

Answers (1)

abarnert
abarnert

Reputation: 365597

Usually, what you're trying to do is a good idea. But it won't work in this case. The code that's calling getFilepast isn't something you write, it's code deep inside tkinter, and it has no idea what to do with a path that you return to it.

The usual way to deal with this is to create a class, and store values as an instance of the class, like this:

class PathyThing:
    def __init__(self):
        self.browsebutton2 = Button(root, text="Last Week's Report", command=self.getFilepast)
        self.browsebutton2.grid(row=0, column=1)
        # etc.

    def getFilepast(self):
        # open dialog box to select file
        self.pathpast = filedialog.askopenfilename(initialdir="/", title="Select file")

    # etc.

pathy = PathyThing()

Now, any other method of pathy can see self.pathpast.

Often, you want to make this class a subclass of something like tkinter.Frame, and then create a PathyFrame instead of a normal Frame. There are examples of this in most tkinter tutorials.


I think you may have also wanted to create a single function that handles both buttons' callbacks. You can do that by using partial to pass an extra argument to the function. But with your example, you're kind of stuck—the only real difference between the two functions is which variable they set, and there's no nice way to pass that information down. Usually, however, you want to actually do something, not just store a value in a variable. For example, let's say we wanted to read the first line from the report file and set the contents of a label to match it. Then we'd have something we can factor out:

from functools import partial

def getPath(label):
    path = filedialog.askopenfilename(initialdir='/', title="Select file")
    with open(path) as f:
        firstline = next(f)
    label.config(text=firstline)

label = Label(root)
label.grid(row=1, column=0)
browsebutton = Button(root, text="This Week's Report", command=partial(getFile, label))
browsebutton.grid(row=0, column=0)

label2 = Label(root)
label.grid(row=1, column=1)
browsebutton2 = Button(root, text="Last Week's Report", command=partial(getFile, label2))
browsebutton2.grid(row=0, column=1)

Upvotes: 1

Related Questions