Jump to content

Python GUIzero not parsing variables outside function

Aspect11

So I am trying to make a GUI inside of python using GUIzero, but am having trouble moving the variables outside the function.

The code:

import re
import webbrowser
from guizero import App, Text, PushButton, TextBox, CheckBox

fileName = ""
selectedFormat = ""

def GUI():
    global fileName
    global selectedFormat
    def submit(selectedFormat):
        fileName = name.value
        selectionPDFSelected = boxPDF.value
        selectionMOBISelected = boxMOBI.value
        selectionEPUBSelected = boxEPUB.value
        if fileName != None:
            fileName = re.search('[a-zA-Z0-9]+', fileName).group()
            if selectionPDFSelected or selectionMOBISelected or selectionEPUBSelected == 1:
                if selectionPDFSelected == 1:
                    selectedFormat = "PDF"
                elif selectionMOBISelected == 1:
                    selectedFormat = "MOBI"
                elif selectionEPUBSelected == 1:
                    selectedFormat = "EPUB"

                print(fileName, selectedFormat)
                app.destroy()
            else:
                print("No format selected, please try again")
        else:
            print("No file name inputted, please try again")

    app = App(layout="grid", width ="525", height="100", title="AO3 Downloader")

    name_label = Text(app, text="Please enter the filename without the extension:", grid=[0, 0], align="left")
    name = TextBox(app, text="", grid=[1, 0])

    selection_label = Text(app, text="Please tick which format you want to download to:", grid=[0, 1], align="left")    #
    boxPDF = CheckBox(app, text="PDF", grid=[1, 1])
    boxMOBI = CheckBox(app, text="MOBI", grid=[2, 1])
    boxEPUB = CheckBox(app, text="EPUB", grid=[3, 1])

    submit_button = PushButton(app, text="Submit", align="bottom", grid=[0, 4])
    submit_button.when_clicked = submit

    app.display()

GUI()
print(fileName, selectedFormat)

So when I run this program, it prints out the file name and format perfectly inside of the function. But when I want to receive the output outside the function like with the bottom statement. It just returns with nothing.

 

If anyone can help, it will be appreciated. Thanks!

Specs:

Motherboard: Gigabyte Z97X Gaming 3

CPU: Intel Core I7 4790K

GPU: Gigabyte G1 Gaming GTX 970

RAM: HyperX Fury 16GB

HDD: Seagate ST3000DM001 3TB

SSD: KINGSTON SV300S37A480G 450GB

Cooler: Corsair H100i GTX

Case: NZXT H440 Red

Monitor: DELL U2412M

Keyboard: Gigabyte Force K7

Mouse: Corsair Sabre RGB

 

Link to comment
Share on other sites

Link to post
Share on other sites

I just want to put a solution here since the link was a little confusing as it's using Python 2 and sorry if this is late. Firstly, if your selectedFormat var is global you don't need to be passing it as a param. I'm actually surprised it didn't crash since it doesn't look like it's being passed at all. Secondly, I'm firm believer of avoiding globals as much as possible since it's hard to keep track. However, an easy solution without avoiding globals would be to do this:

...
def GUI():
    def submit():
        global fileName
        global selectedFormat
        fileName = name.value
...

The global keyword makes those variables available inside and outside the scope of the function. So you can now access them in your main body. 

 

I'm not familiar with GUIZero or how your application is designed, but I'd highly recommend using objects. Like this:

import re
import webbrowser
from guizero import App, Text, PushButton, TextBox, CheckBox

class fileSelect:
    fileName = ""
    selectedFormat = ""
    def __init__(self):
        self.app = App(layout="grid", width ="525", height="100", title="AO3 Downloader")
        self.name_label = Text(self.app, text="Please enter the filename without the extension:", grid=[0, 0], align="left")
        self.name = TextBox(self.app, text="", grid=[1, 0])

        self.selection_label = Text(self.app, text="Please tick which format you want to download to:", grid=[0, 1], align="left")    #
        self.boxPDF = CheckBox(self.app, text="PDF", grid=[1, 1])
        self.boxMOBI = CheckBox(self.app, text="MOBI", grid=[2, 1])
        self.boxEPUB = CheckBox(self.app, text="EPUB", grid=[3, 1])

        self.submit_button = PushButton(self.app, text="Submit", align="bottom", grid=[0, 4])
        self.submit_button.when_clicked = self.submit
    def display(self):
        self.app.display()
    def submit(self):
        self.fileName = self.name.value
        selectionPDFSelected = self.boxPDF.value
        selectionMOBISelected = self.boxMOBI.value
        selectionEPUBSelected = self.boxEPUB.value
        if self.fileName != None:
            fileName = re.search('[a-zA-Z0-9]+', self.fileName).group()
            if selectionPDFSelected or selectionMOBISelected or selectionEPUBSelected == 1:
                if selectionPDFSelected == 1:
                    self.selectedFormat = "PDF"
                elif selectionMOBISelected == 1:
                    self.selectedFormat = "MOBI"
                elif selectionEPUBSelected == 1:
                    self.selectedFormat = "EPUB"

                print(self.fileName, self.selectedFormat)
                self.app.destroy()
            else:
                print("No format selected, please try again")
        else:
            print("No file name inputted, please try again")
            
#Example of a simple reusable message box that takes data
class messageBox:
    def __init__(self, message):
        self.app = App(layout="grid", width ="250", height="100", title="Success")
        self.message = Text(self.app, text=message, grid=[0, 0], align="left")

        self.submit_button = PushButton(self.app, text="OK!", align="bottom", grid=[1, 4])
        self.submit_button.when_clicked = self.destroy
    def destroy(self):
        self.app.destroy()

fileSelectGUI = fileSelect()
fileSelectGUI.display()

messageBox(f"{fileSelectGUI.fileName}.{fileSelectGUI.selectedFormat} selected!")

print(fileSelectGUI.fileName, fileSelectGUI.selectedFormat)

You'll have a nice reusable file select module, that has the filename and format ready to be accessed (and/or modified). Like I said, I'm not familiar with the framework so I'm probably missing something here since  an app is getting created and destroyed per object. I'm pretty sure that's not optimal behaviour but you can see how you could just modify app widgets of an object using its interface. 

 

Hope this helps. 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×