New shell_with_animation function to help long-running operations

This commit is contained in:
PySimpleGUI 2020-02-24 14:12:09 -05:00
parent 40e823e2dd
commit 6982c4078d
1 changed files with 65 additions and 4 deletions

View File

@ -126,6 +126,9 @@ import warnings
from math import floor from math import floor
from math import fabs from math import fabs
from functools import wraps from functools import wraps
from subprocess import run, PIPE
from threading import Thread
warnings.simplefilter('always', UserWarning) warnings.simplefilter('always', UserWarning)
@ -12961,8 +12964,7 @@ def PopupGetText(message, title=None, default_text='', password_char='', size=(N
# --------------------------- PopupAnimated --------------------------- # --------------------------- PopupAnimated ---------------------------
def PopupAnimated(image_source, message=None, background_color=None, text_color=None, font=None, no_titlebar=True, def PopupAnimated(image_source, message=None, background_color=None, text_color=None, font=None, no_titlebar=True, grab_anywhere=True, keep_on_top=True, location=(None, None), alpha_channel=None,
grab_anywhere=True, keep_on_top=True, location=(None, None), alpha_channel=None,
time_between_frames=0, transparent_color=None): time_between_frames=0, transparent_color=None):
""" """
Show animation one frame at a time. This function has its own internal clocking meaning you can call it at any frequency Show animation one frame at a time. This function has its own internal clocking meaning you can call it at any frequency
@ -13001,7 +13003,7 @@ def PopupAnimated(image_source, message=None, background_color=None, text_color=
window = Window('Animated GIF', layout, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, window = Window('Animated GIF', layout, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere,
keep_on_top=keep_on_top, background_color=background_color, location=location, keep_on_top=keep_on_top, background_color=background_color, location=location,
alpha_channel=alpha_channel, element_padding=(0, 0), margins=(0, 0), alpha_channel=alpha_channel, element_padding=(0, 0), margins=(0, 0),
transparent_color=transparent_color).Finalize() transparent_color=transparent_color, finalize=True, element_justification='c')
Window._animated_popup_dict[image_source] = window Window._animated_popup_dict[image_source] = window
else: else:
window = Window._animated_popup_dict[image_source] window = Window._animated_popup_dict[image_source]
@ -13011,7 +13013,7 @@ def PopupAnimated(image_source, message=None, background_color=None, text_color=
# Popup Notify # Popup Notify
def popup_notify(*args, title='', icon=_tray_icon_success, display_duration_in_ms=SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS, def popup_notify(*args, title='', icon=SYSTEM_TRAY_MESSAGE_ICON_INFORMATION, display_duration_in_ms=SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS,
fade_in_duration=SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION, alpha=0.9, location=None): fade_in_duration=SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION, alpha=0.9, location=None):
""" """
Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message. It is more like a "toaster" window than the normal popups. Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message. It is more like a "toaster" window than the normal popups.
@ -13057,6 +13059,65 @@ def popup_notify(*args, title='', icon=_tray_icon_success, display_duration_in_m
return SystemTray.notify(title=title, message=message, icon=icon, display_duration_in_ms=display_duration_in_ms, fade_in_duration=fade_in_duration, alpha=alpha, location=location) return SystemTray.notify(title=title, message=message, icon=icon, display_duration_in_ms=display_duration_in_ms, fade_in_duration=fade_in_duration, alpha=alpha, location=location)
#####################################################################
# Animated window while shell command is executed
#####################################################################
def _process_thread(*args):
global __shell_process__
# start running the command with arugments
try:
__shell_process__ = run(args, shell=True, stdout=PIPE)
except:
__shell_process__ = None
def shell_with_animation(command, args=None, image_source=DEFAULT_BASE64_LOADING_GIF, message=None, background_color=None, text_color=None, font=None, no_titlebar=True, grab_anywhere=True, keep_on_top=True, location=(None, None), alpha_channel=None, time_between_frames=100, transparent_color=None):
"""
Execute a "shell command" (anything capable of being launched using subprocess.run) and
while the command is running, show an animated popup so that the user knows that a long-running
command is being executed. Without this mechanism, the GUI appears locked up.
:param command: (str) The command to run
:param args: List[str] List of arguments
:param image_source: Union[str, bytes] Either a filename or a base64 string.
:param message: (str) An optional message to be shown with the animation
:param background_color: (str) color of background
:param text_color: (str) color of the text
:param font: Union[str, tuple) specifies the font family, size, etc
:param no_titlebar: (bool) If True then the titlebar and window frame will not be shown
:param grab_anywhere: (bool) If True then you can move the window just clicking anywhere on window, hold and drag
:param keep_on_top: (bool) If True then Window will remain on top of all other windows currently shownn
:param location: (int, int) (x,y) location on the screen to place the top left corner of your window. Default is to center on screen
:param alpha_channel: (float) Window transparency 0 = invisible 1 = completely visible. Values between are see through
:param time_between_frames: (int) Amount of time in milliseconds between each frame
:param transparent_color: (str) This color will be completely see-through in your window. Can even click through
:return: (str) The resulting string output from stdout
"""
global __shell_process__
real_args = [command]
if args is not None:
real_args.append(args)
thread = Thread(target=_process_thread, args=real_args, daemon=True)
thread.start()
# Poll to see if the thread is still running. If so, then continue showing the animation
while True:
popup_animated(image_source=image_source, message=message, time_between_frames=time_between_frames, transparent_color=transparent_color, text_color=text_color, background_color=background_color, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, alpha_channel=alpha_channel)
thread.join(timeout=time_between_frames/1000)
if not thread.is_alive():
break
popup_animated(None) # stop running the animation
output = __shell_process__.__str__().replace('\\r\\n', '\n') # fix up the output string
return output
##################################################################################################### #####################################################################################################
# Debugger # Debugger
##################################################################################################### #####################################################################################################