-1

I'm creating a tkinter GUI for the purposes of opening and analyzing an EDF file named "raw" using the mne package. Currently, when I run the script, named "my_script.py", it first prompts me to open a file using the following code:

window = Tk()

window.filename = filedialog.askopenfilename(initialdir = "Users/fishbacp/Desktop",title = 
"Select file",filetypes = (("EDF files","*.edf"),("all files","*.*")))
raw = mn.io.read_raw_edf(window.filename, preload=True)

# Now perform my first operation on the returned file, "raw":
data,times=raw[:,:]

# In subsequent lines I fill my gui with checkboxes, input boxes, labels etc. to perform more tasks.

This works fine, but the file dialog starts before I see the various widgets in my window.

Now I want to run the module so that instead of the file dialog starting automatically, I first see the GUI and then use a button in it to run the file dialog. Here's my attempt:

window = Tk()

def open_file():
    window.filename = filedialog.askopenfilename(initialdir = "Users/fishbacp/Desktop",title 
    = "Select file",filetypes = (("EDF files","*.edf"),("all files","*.*")))
    raw = mn.io.read_raw_edf(window.filename, preload=True)
    return raw

open_file_button=Button(window, bg='lightgray',text="Select 
              File",command=open_file)
open_file_button.grid(row=0,column=0,padx=10, pady=10)

# Now perform my first operation on the returned file, "raw":
data,times=raw[:,:]

The error message states, "Traceback (most recent call last): File "/Users/fishbacp/Desktop/my_script.py", line 67, in data,times=raw[:,:] NameError: name 'raw' is not defined

So, I'm missing something basic about how tkinter works in terms of what I should be doing to get my open_file function return the raw file as I want.

fishbacp
  • 1,123
  • 3
  • 14
  • 29

1 Answers1

1

You cannot return something from the command callback. Your code processing raw content depends on the fact a button has been clicked by the user. It hence has to be located in the callback itself.

Some more clarification:

When creating a UI, you go from procedural programing (one thing after the other) to event driven programing: a User event triggers the next operation the program will do. It is because the user will click "open file" button that you can process the data. The call to windows.mainloop() tells TK to start processing user events (clicks,...). In practice you cannot do anything on the edf file as long as user has not clicked on the button so it makes sense to put all this code in the callback.

Something like: is a starting point:

window = Tk()

def open_file():

    window.filename = filedialog.askopenfilename(initialdir = "Users/fishbacp/Desktop",title 
    = "Select file",filetypes = (("EDF files","*.edf"),("all files","*.*")))
    raw = mn.io.read_raw_edf(window.filename, preload=True)

    # Now perform my first operation on the returned file, "raw":
    # this can be done only once the user has selected the file to open
    # which is "triggered" by the user clicking on "Select File"
    data,times=raw[:,:]
    ...


open_file_button=Button(window, bg='lightgray',text="Select 
              File",command=open_file)
open_file_button.grid(row=0,column=0,padx=10, pady=10)
Jean-Marc Volle
  • 3,113
  • 1
  • 16
  • 20
  • Thanks, so I see how instead of using a return command, we set raw as a global variable inside open_file, and we have to set raw to None before open_file because we need it defined prior to the command data,times=raw[:,:] which is outside the function. This results in the error TypeError: 'NoneType' object is not subscriptable I see why this is but not how to overcome it. – fishbacp Jun 06 '20 at 15:06
  • Also, currently, an enormous of amount of work is being down outside the function open_file, where I perform various calculations, create graphs, etc. The script ends with window.mainloop(). Are you suggesting all of this work prior to window.mainloop() be done inside open_file? – fishbacp Jun 06 '20 at 15:08
  • When creating a UI, you go from procedural programing (one thing after the other) to event driven programing: a User event triggers the next operation the program will do. It is because the user will click "open file" button that you can process the data. The call to `windows.mainloop()` tells TK to start processing user events (clicks,...). In practice you cannot do anything on the edf file as long as user has not clicked on the button so it makes sense to put all this code in the callback. This will make the UI unresponsive until the work is done. – Jean-Marc Volle Jun 06 '20 at 15:31
  • About not blocking the UI main loop you can check: https://stackoverflow.com/questions/16745507/tkinter-how-to-use-threads-to-preventing-main-event-loop-from-freezing – Jean-Marc Volle Jun 06 '20 at 15:38
  • Thank you. As someone new to Tkinter, your distinction between procedural and event driven is very helpful and shows how I must now look at things. – fishbacp Jun 06 '20 at 15:43