Added animated GIF to tasks that take a long time but are unable to provide regular updates.

This commit is contained in:
PySimpleGUI 2019-11-29 22:01:50 -05:00
parent 235ead0f79
commit b74ec7126c
1 changed files with 22 additions and 12 deletions

View File

@ -5,12 +5,15 @@ import PySimpleGUI as sg
"""
DESIGN PATTERN - Multithreaded Long Tasks GUI using shared global variables
Presents one method for running long-running operations in a PySimpleGUI environment.
The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
The "long work" is contained in the thread that is being started.
The "long work" is contained in the thread that is being started. Communicating is done (carefully) using global variables
The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined,
a Window is created, and an event loop is executed.
There are 2 ways "progress" is being reported to the user. If a the amount of time is known ahead of time and
the work can be broek down into countable units, then a progress bar is used. If a task is one long chunk
of time that cannot be broken down into smaller units, then an animated GIF is shown that spins as
long as the task is running.
"""
thread_done = 1
@ -29,7 +32,7 @@ def long_operation_thread(seconds):
global thread_done, message, thread_counter, progress
print('Starting thread - will sleep for {} seconds'.format(seconds))
print('Thread started - will sleep for {} seconds'.format(seconds))
thread_counter += 1
for i in range(int(seconds*10)):
time.sleep(.1) # sleep for a while
@ -50,23 +53,28 @@ def the_gui():
sg.change_look_and_feel('Light Brown 3')
layout = [[sg.Text('Long task to perform example')],
[sg.Output(size=(70, 12))],
[sg.Output(size=(80, 12))],
[sg.Text('Number of seconds your task will take'),
sg.Input(key='-SECONDS-', size=(5, 1)),
sg.Button('Do Long Task', bind_return_key=True)],
sg.Button('Do Long Task', bind_return_key=True),
sg.CBox('ONE chunk, cannot break apart', key='-ONE CHUNK-')],
[sg.Text('Work progress'), sg.ProgressBar(total, size=(20,20), orientation='h', key='-PROG-')],
[sg.Button('Click Me'), sg.Button('Exit')], ]
window = sg.Window('Multithreaded Window', layout)
one_chunk = False
sg.popup_animated(None)
# --------------------- EVENT LOOP ---------------------
while True:
event, values = window.read(timeout=100)
event, values = window.read(timeout=400)
if event in (None, 'Exit'):
break
elif event.startswith('Do'):
seconds = float(values['-SECONDS-'])
print('Thread ALIVE! Long work....sending value of {} seconds'.format(seconds))
one_chunk = values['-ONE CHUNK-']
print('Thread Starting! Long work....sending value of {} seconds'.format(seconds))
threading.Thread(target=long_operation_thread, args=(seconds, ), daemon=True).start()
elif event == 'Click Me':
print('Your GUI is alive and well')
@ -75,11 +83,13 @@ def the_gui():
print('The thread has finished!')
print(f'message = {message}')
# reset everything for the next run
thread_done = False
message = ''
progress = 0
sg.popup_animated(None) # just in case one's running, stop it
thread_done = one_chunk = False
message, progress = '', 0
window['-PROG-'].update_bar(total, total) # show the bar as maxed out
if progress != 0:
if one_chunk: # flag signifies the thread is taking to take one big chunk of time
sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, background_color='white', transparent_color='white', time_between_frames=100)
elif progress != 0:
window['-PROG-'].update_bar(progress, total) # update the progress bar if non-zero
# if user exits the window, then close the window and exit the GUI func