0

I am trying to get a value from a closure in an other module. When I press the button in the GUI the file dialog creates a string with the path of the file (so this step works). The string should then be accessible in the main.py. This step doesn't work, in the main it's always None.

This is what I have in file main.py:

import mat_import
import GUI

filename1 = GUI.gui()

print(filename1)

This is what I have in the GUI.py

from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
import os
import math
import sys

def gui():
    mainpage = Tk()   

    def choose_file1():
        filename1 = filedialog.askopenfilename()
        lbl_read_file1_path = Label()
        lbl_read_file1_path.configure(text = filename1)
        lbl_read_file1_path.grid(column=1, row=5, sticky="W", columnspan=3)
        return filename1

    def returnfile1():
        return choose_file1()

    button_read_file1 = Button(mainpage, text="Durchsuchen...", command = returnfile1)
    button_read_file1.config(height = 1, width = 15)
    button_read_file1.grid(column=0, row=5, sticky="W")

    mainloop()

What do I have to change to "print" the string with the filename from function choose_file1 (defined inside the function gui) in file main.py?

Aimery
  • 1,559
  • 1
  • 19
  • 24
Rainer
  • 19
  • 1
  • 8
  • 2
    `gui()` function does not have any `return` statement, therefore its return value is always `None`. You should probably `return` something after calling `mainloop()`. – yeputons May 30 '18 at 09:28
  • As far as I can tell, your `GUI.gui()` function does not return any value. – Aimery May 30 '18 at 09:28
  • @yeputons But when i return "filename1" it says that filename1 is not defined in gui – Rainer May 30 '18 at 09:31
  • 1
    @Rainer Where is the output of `returnfile1` stored? I suspect it isn't. Besides, `filename1` is a variable local to `choose_file1`, `gui` can't know about it. – Aimery May 30 '18 at 09:33
  • That's something worth to be a part of the question. That's also correct: `filename1` is a variable local to `choose_file1`. If you want to access it from `gui()`, you can declare it in `gui()` and then use `nonlocal` in `choose_file1()` (see [here](https://stackoverflow.com/questions/1261875)). – yeputons May 30 '18 at 09:34
  • @Aimery Which output do you mean? Do you mean the path of the file to choose? It is stored in "filename1" inside of the main.py and should get the returned value from the gui. Would you define filename1 global? – Rainer May 30 '18 at 09:38
  • About `return`: https://stackoverflow.com/questions/7129285/what-is-the-purpose-of-the-return-statement#7129293 and https://stackoverflow.com/questions/7129285/what-is-the-purpose-of-the-return-statement#7129293 – Aimery May 30 '18 at 09:39
  • @Rainer The output of a function is the value it returns. **Don't** use globals. As @yeputons said, you need to 1. store the value returned by `returnfile1` in a variable defined in `gui` and 2. add a `return` statement at the end of `gui` so said value is stored in `filename1` (defined in main.py). – Aimery May 30 '18 at 09:42
  • @Aimery Thank you. Now I have the filename1 in main.py. It's not the sting but this: .returnlile1>. I added filename1=choose_file1() and return filename1 inside of returnfile1(). I also added filename1=returnfile1 and return filename1 after mainloop() – Rainer May 30 '18 at 10:08

1 Answers1

3

There are two main problems with your code:

  • Function gui does not have an explicit return value. So when you call it, it returns None

  • The value returned by returnfile1 (which is obtained from choose_file1) is not stored in a variable, so is lost when the function exits.

Here is quick fix to get your code to work (no changes are required in "main.py"):

from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
import os
import math
import sys

def gui():
    mainpage = Tk()
    # Variable to store the filename
    filename1 = "" 

    def choose_file1():
        # We want to use the same variable filename1 we declared above
        nonlocal filename1
        filename1 = filedialog.askopenfilename()
        lbl_read_file1_path = Label()
        lbl_read_file1_path.configure(text = filename1)
        lbl_read_file1_path.grid(column=1, row=5, sticky="W", columnspan=3)
        # No return statement is needed here

    # Function 'returnfile1' is not needed.

    button_read_file1 = Button(mainpage, text="Durchsuchen...", command = choose_file1)
    button_read_file1.config(height = 1, width = 15)
    button_read_file1.grid(column=0, row=5, sticky="W")

    mainloop()

    # Return the value of filename1
    return filename1
Aimery
  • 1,559
  • 1
  • 19
  • 24
  • If you plan on working on more advanced GUIs using Python and tkinter, you may want to read about Object Oriented Programming. – Aimery May 30 '18 at 09:57
  • This answer would be better if you described what you changed. Otherwise we have to read the code line-by-line and compare it to the original to see what you did differently. – Bryan Oakley May 30 '18 at 11:41
  • @BryanOakley Is it better now? – Aimery May 30 '18 at 12:34
  • Yes, much better. – Bryan Oakley May 30 '18 at 12:35
  • This is the right idea in terms of code structure generally, but it won't work *because of what `mainloop` does*. The overall problem is that the way that OP wants to organize the code simply doesn't make any sense. – Karl Knechtel Sep 13 '22 at 15:23