0

So here is my problem that I just can't figure out and can't seem to find information to help me understand what is happening. So I set source equal to the button that calls a function called openDirectory which is really just a short-cut to call os.path.join() and os.path.normalize() on the askopendirectory function from tkinter.filedialog.

The problem is that the source is always a number and I can't figure out why it is not the path I have chosen in the openDirectory function. I have also tried placing the code inside openDirectory directly in the command of the button, and it still does the same thing.

Steps to reproduce:

  1. Run this code (written using python 3.5)
  2. Select a path using the source button
  3. Hit the button at the bottom right corner which should show the path in a messagebox
  4. Notice that the messagebox shows a big number instead of the path.

How can I get the path stored in the source variable so I can access it at any time?

#!/usr/bin/python
import os
from functions import *
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog


class FileMover(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()

    def openDirectory(listfiles, recursive):
        destination = os.path.join(os.path.normpath(filedialog.askdirectory()), "")
        return destination

    def initUI(self):
        self.parent.title("File Mover")
        self.pack()

        recursiveCheck = bool
        previewCheck = bool

        # source button and label. source should equal the path selected in openDirecotry
        source = Button(self, text="Source Directory", command=lambda:openDirectory(recursiveCheck))
        sourceLabel = Label(self, text="Select a Source Directory...")
        sourcemsg = Button(self, text="Source Variable", command=lambda:messagebox.askokcancel(self, source))

        # check box used to tell open directory either true or false to recurse the source dir
        recursiveLabel = Label(self, text="Recursive ")
        recursive = Checkbutton(self, onvalue=True, offvalue=False, variable=recursiveCheck)

        # destination button and label. source should equal the path selected in openDirecotry
        destination = Button(self, text="Target Directory ", command=lambda:openDirectory(False))
        destinationLabel = Label(self, text="Select a Target Directory...")

        # not implemented yet
        previewLabel = Label(self, text="Preview ")
        preview = Checkbutton(self, onvalue=True, offvalue=False, variable=previewCheck)

        source.grid(row=0, column=0, columnspan=2)
        sourceLabel.grid(row=0, column=2)
        recursiveLabel.grid(row=1, column=1)
        recursive.grid(row=1, column=2, sticky=W)
        destination.grid(row=2, column=0, columnspan=2)
        destinationLabel.grid(row=2, column=2)
        previewLabel.grid(row=4, column=6)
        preview.grid(row=4, column=7, sticky=W)
        # just for debugging to show source directory on demand
        sourcemsg.grid(row=5, column=8)

def main():
    root = Tk()
    ex = FileMover(root)
    root.mainloop()

if __name__ == '__main__':
    main()
martineau
  • 99,260
  • 22
  • 139
  • 249
balfred
  • 49
  • 6
  • Might help: http://stackoverflow.com/questions/11295917/how-to-select-a-directory-and-store-the-location-using-tkinter-in-python – wbrugato Sep 16 '16 at 22:41

1 Answers1

1

Buttons do not work that way. When a function serves as a button's callback and the function is called by using the button, there's nowhere to return to. There isn't really a sensible way to make that work. If it worked the way you are guessing it does, you would lose the reference to the button! You don't want that.

Instead, simply save it as an instance variable:

def openDirectory(self, recursive):
    self.destination = os.path.join(os.path.normpath(filedialog.askdirectory()), "")

Note that your openDirectory method had listfiles referring to the instance itself, while the other methods use the traditional self - I've changed it to use self so you don't have to deal with listfiles.destination = ....

sourcemsg = Button(self, text="Source Variable", command=lambda:messagebox.askokcancel('Window Title', self.destination))

Note that I've changed the arguments to messagebox.askokcancel to the string 'Window Title' and the reference self.destination, so instead of the window's title being a reference to the frame (it's supposed to be a string for the window's title) it's an actual string, and instead of the message's text being a reference to a button (it's supposed to be a string for the message's text) it's the string you saved in openDirectory.

TigerhawkT3
  • 44,764
  • 6
  • 48
  • 82
  • You rock! I never thought about it that way but it makes perfect sense based on the explanation you gave. Thank you so much! – balfred Sep 16 '16 at 23:00