Let's assume the following problem: we have an Ipywidget button and a progress bar. On clicking the button, a function work() is executed, which merely fills the progress bar until completing it, then reverses the process and empties it out. As it stands, such a function runs continuously. The following code snippet provides the corresponding MWE:
# importing packages.
from IPython.display import display
import ipywidgets as widgets
import time
import functools
# setting 'progress', 'start_button' and 'Hbox' variables.
progress = widgets.FloatProgress(value=0.0, min=0.0, max=1.0)
start_button = widgets.Button(description="start fill")
Hbox = widgets.HBox(children=[start_button, progress])
# defining 'on_button_clicked_start()' function; executes 'work()' function.
def on_button_clicked_start(b, start_button, progress):
work(progress)
# call to 'on_button_clicked_start()' function when clicking the button.
start_button.on_click(functools.partial(on_button_clicked_start, start_button=start_button, progress=progress))
# defining 'work()' function.
def work(progress):
total = 100
i = 0
# while roop for continuous run.
while True:
# while loop for filling the progress bar.
while progress.value < 1.0:
time.sleep(0.01)
i += 1
progress.value = float(i)/total
# while loop for emptying the progress bar.
while progress.value > 0.0:
time.sleep(0.01)
i -= 1
progress.value = float(i)/total
# display statement.
display(Hbox)
The aim is to include "Stop" and "Resume" buttons, so that the while loops are broken whenever the first is clicked, and the execution is resumed when pressing the second one. Can this be done without employing threading, multiprocessing or asynchronicity?
Here's an answer I derived by means of the threading package and based on the background-working-widget example given in https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Asynchronous.html. It's certainly not optimized, and probably not good-practice-compliant. Anybody coming up with a better answer is welcomed to provide it.