Python - PySimpleGUI - Lock Relative Position of Windows (or Loading Animation Overlay)

224 views Asked by At

I've created an application to run a query and download some files from a database. I want to indicate the application is still running while the query resolves. Currently, the loading animation popup appears over the main window. However, when I minimize the main window, the popup remains. I want to popup to appear, disappear (minimize), and move relative to the main window.

I have not delved into the Tkinter documentation yet. I'm not sure how it would interact with PySimpleGUI. I'm hoping to just use PySimpleGUI, but I am open to other solutions.

I'd like to also use the modal functionality for it. The main window shouldn't support interaction while the download script is running.

enter image description here

enter image description here

import PySimpleGUI as psg

def download_thread():
    pass

psg.theme('GrayGrayGray')

layout = [
    [psg.Frame("Query",[
            [psg.Button('Open File'), psg.Button('Save File'), psg.Text('Untitled.sql', key = '-DOCNAME-')],
            [psg.Multiline(size = (120,30), key = '-TEXTBOX-', font='Consolas 12', no_scrollbar=True, expand_x=True)],
        ])],
    [psg.Column([[psg.Button('Download Files'),psg.Cancel()]], justification='right')]
    
]
window = psg.Window('File Download Tool', layout)

loading = False
while True:
    event, values = window.read(timeout = 10)
    if event == psg.WIN_CLOSED or event == 'Exit':
        break

    if loading:
        psg.popup_animated(psg.DEFAULT_BASE64_LOADING_GIF, time_between_frames=100)    
    else:
        psg.popup_animated(None)

    if event == 'Download Files':
        loading = True
        download_thread() # pretend this is threaded

    if event == 'Cancel':
        loading = False
1

There are 1 answers

4
Jason Yang On

It won't work if you use the popup_animated provided by PySimpleGUI, try to design one by yourself if you need something different or special.

Following code demo the way by binding event '<Configure>' to popup window to move main window with same delta position, also with option modal=True of popup window to have this window be the only window a user can interact with until it is closed.

from time import sleep
import threading
import PySimpleGUI as sg

def popup(main_window, window=None, duration=0, image=sg.DEFAULT_BASE64_LOADING_GIF):
    global x0, y0, x1, y1, user_event
    if window is None:
        layout = [[sg.Image(data=image, enable_events=True, key='-IMAGE-')]]
        x0, y0 = main_window.current_location(more_accurate=True)
        w0, h0 = main_window.current_size_accurate()
        window = sg.Window('Title', layout, no_titlebar=True, grab_anywhere=True,
            background_color='blue', element_padding=(0, 0), margins=(0, 0), finalize=True, modal=True)
        w1, h1 = window.current_size_accurate()
        x1, y1 = x0+(w0-w1)//2, y0+(h0-h1)//2
        window.move(x1, y1)
        window.refresh()
        window.bind("<Configure>", 'Configure')
    else:
        window['-IMAGE-'].update_animation(image, time_between_frames=duration)
    event, values = window.read(1)
    if event == 'Configure':
        if user_event:
            user_event = False
        else:
            x11, y11 = window.current_location(more_accurate=True)
            x00, y00 = main_window.current_location(more_accurate=True)
            if (x11, y11) != (x1, y1):
                x0, y0 = x0+x11-x1, y0+y11-y1
                main_window.move(x0, y0)
                x1, y1 = x11, y11
            elif (x00, y00) != (x0, y0):
                x1, y1 = x1+x00-x0, y1+y00-y0
                window.move(x1, y1)
                x0, y0 = x00, y00
                user_event = True
    return window

def download(window):
    sleep(5)
    window.write_event_value('Done', None)

sg.theme('GrayGrayGray')

layout = [
    [sg.Frame("Query",[
            [sg.Button('Open File'), sg.Button('Save File'), sg.Text('Untitled.sql', key = '-DOCNAME-')],
            [sg.Multiline(size = (120,30), key = '-TEXTBOX-', font='Consolas 12', no_scrollbar=True, expand_x=True)],
        ])],
    [sg.Column([[sg.Button('Download Files'),sg.Cancel()]], justification='right')]

]
window = sg.Window('File Download Tool', layout, finalize=True)
loading, popup_win, x1, y1, user_event = False, None, None, None, False
x0, y0 = window.current_location(more_accurate=True)

while True:
    event, values = window.read(timeout = 10)
    if event == sg.WIN_CLOSED or event == 'Exit':
        break

    elif event == sg.TIMEOUT_EVENT and loading:
        popup_win = popup(window, popup_win, duration=100)

    elif event == 'Download Files':
        loading = True
        threading.Thread(target=download, args=(window, ), daemon=True).start()

    elif event == 'Done':
        popup_win.close()
        loading, popup_win = False, None

window.close()