Python Forum

Full Version: GUI freezes while executing a callback funtion when a button is pressed
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I'm using PySimpleGUI and PyAutoGUI to automate a very tedious Excel to Enovia data migration project, where my task is to look for a part on Enovia, type in specific attributes from excel and save it. I came up with this, it takes these initial conditions, manipulates the mouse and keyboard and edits the part for me.

The makeChanges() function has been tested extensively standalone and is doing great at editing it. However when I use the 'Edit' button, it executes the makeChanges() function except it freezes the GUI and will essentially crash if messed with, unless the entire makeChanges() function has executed, and only then is the GUI manipulatable.

    
    import PySimpleGUI as sg      
    import pyautogui, time, ctypes
    pyautogui.FAILSAFE = True
    pyautogui.PAUSE = 1


    #Setting up lazy variables
    s = time.sleep
    moveToo = ctypes.windll.user32.SetCursorPos#(x, y) coords,
    py = pyautogui


    #Initializing Layout of Window and acquiring initial conditions
    layout = [[sg.Text('Please enter initial conditions(Only the first two letters)')],
              [sg.Text('Desired Lines', size=(14, 1)), sg.Input(size=(20,1), key='lines')],
              [sg.Text('Company Name ', size=(14, 1)), sg.InputText(size=(20,1), key='company')],
              [sg.Text('Filetype', size=(14, 1)), sg.InputText(size=(20,1), key='filetype')],
              [sg.Text('Dashnumbers', size=(14, 1)), sg.InputText(size=(20,1), key='dashnumbers')],
              [sg.Button('Edit'), sg.Button('Quit'), sg.Button('Continue')]]  


    window = sg.Window('Automatic Intern', layout)    


    #Button Callback Functions
    def Bu1(): #Button 1
        makeChanges(values['company'], values['dashnumbers'], values['filetype'])

    def Bu2(): #Button 2
        window.Close()



    #Callback Edit Function
    def makeChanges(company, dashnumbers, filetype):
        for i in range(len(lines)): #Convert to integars
            lines[i] = int(lines[i])
            lines[i] -= 1 #Subtract 1 to get real row numbers
            print(lines[i])
        #Parse through lines and make necessary edits
        for n, val in enumerate(lines): #Iterate through each element
            print(lines[n]) #Print element value
            py.moveTo(497,258,0.5)#Move to First Dropdown Marker, Checkpoint 1
            py.moveRel(0,30*lines[n])
            #Add another function that exectues the edit
            py.click()
            py.moveRel(73, 124)
            py.click()
            s(2.5)
            py.moveTo(249, 256)#Moving to and Clicking Hamburger Menu
            py.click()
            py.moveTo(273, 281)#Moving to and Clicking Edit Details
            py.click()
            py.moveTo(394, 786)#Moving to 'Customer' dropdown
            py.click()
            py.typewrite(company)#Typewrite given Company
            py.hotkey('tab')
            py.typewrite(dashnumbers)#Typein
            py.hotkey('space')
            py.hotkey('tab')
            py.typewrite(filetype)#Given Filetype
            py.hotkey('tab')
            py.hotkey('enter')
            py.moveTo(843, 98)#Move and Click Search Bar
            py.click()
            py.moveTo(806, 125)#Click last search result
            py.click()
            s(2)
            print('Done')


    event, values = window.Read() #Acquriing data in GUI
    lines = values['lines'].split(' ')
    print(event)

    if event == 'Edit': #Pass onto makeChanges()
        Bu1()
        window.Close()
        print('Executed')
    elif event == 'Quit': #Quit the program
        Bu2()
        window.Close()
What I would like is to for the GUI to be running while the edit function executes instead of freezing, and also in the future, to pause/continue the editing at any given time with buttons I intend to add into the GUI. Please do excuse the ugliness of the code. I'm new and I would love some tips on how to be better, so please do grill me on everything that makes you cringe. Big Grin
PySimpleGUI is fairly new, by a new python user, and has a small following. And it is a tkinter wrapper basically. I dont know really anyone that uses it so i am unsure of anyone that could help with it. To be honest you would get more help using tkinter itself as it is more popular.
If you was using tkinter directly you could use techniques shown in the following thread
https://python-forum.io/Thread-Tkinter-H...ng-the-gui
Try posting an Issue on the PySimpleGUI project GitHub. It looks like support is good looking at the Issues and how quickly they are responded to.
This would be a similar layout. Haven't used tkinter in years so im rusty with it, but you could make it look exactly like it with some tinkering. If you wanted to add another input field then just add to the labels list.

root = tk.Tk()
labels = ['Desired Lines', 'Company Name ', 'Filetype', 'Dashnumbers']
inputs = []

label = tk.Label(root, text='Please enter initial conditions(Only the first two letters)').grid(columnspan=2)

def get_entries():
    for inp in inputs:
        print(inp.get())

for i, label in enumerate(labels, 1):
    tk.Label(root, text=label).grid(row=i, column=0)
    lbl = tk.Entry(root)
    lbl.grid(row=i, column=1)
    inputs.append(lbl)
    
buttons = tk.Frame(root)
buttons.grid(row=i+1, columnspan=2)

tk.Button(buttons, text='Edit', command=get_entries).pack(side='left')
tk.Button(buttons, text='Quit', command=sys.exit).pack(side='left')
tk.Button(buttons, text='Continue', command=get_entries).pack(side='left')

root.mainloop()
(Jul-08-2019, 10:22 PM)abi17124 Wrote: [ -> ]What I would like is to for the GUI to be running while the edit function executes instead of freezing, and also in the future, to pause/continue the editing at any given time with buttons I intend to add into the GUI.

You've run into the classic problem of trying to do a lot of CPU or wall-clock intensive operations. When your program begins to take so much of the processor that you "starve" your GUI of CPU cycles, it's then that you turn to Threads to get yourself out of the problem.

To get through this, you need to startup threads at places where your operations will block for a long time. This program is a demonstration of how to do that with PySimpleGUI:
https://repl.it/@PySimpleGUI/Threaded-fo...long-tasks

You can also run it there and see how it works. To use it just type in the number of seconds you want your function to take and press the button to start it. While that thread is "busy" doing work (sleeping) notice how you can continue to take input from the GUI and act on it.

There's little of your code that you need to change other than to start a thread instead of call a function. If you need to know when the operation completes, then communicate through a queue like in the demo.