So I want to create a simple UI in Jupyter notebook where:
- A counter "number" is incremented every second
- If the checkbox "pause" is checked, "number" is not incremented
- If the button "trigger" is pressed, "number" is decremented, regardless of pause status
So far I tried a few variants of the code below but it doesn't work; it seems like the widget values aren't updating when running the while loop. Is there a way to fix it or another way to do this? Thanks!
import ipywidgets as widgets
import time
from IPython.display import display, clear_output
btn = widgets.Button(description = "Trigger")
pause = widgets.Checkbox(value = False, description = "Paused?")
number = widgets.Label("0")
wid = widgets.VBox([btn, number, pause])
display(wid)
def triggered(b):
number.value = str(int(number.value) - 1)
btn.on_click(triggered)
while True:
time.sleep(1)
while (pause.value == True):
time.sleep(3)
number.value = str(int(number.value) 1)
CodePudding user response:
As mentioned by ac24, the trick is to run your counter function in a different thread. You can use the threading
library to do that. Below, I defined a function counter
and launched it in a different thread. That way, the user is still able to interact with the widgets while the counter
function is running.
An important thing to keep in mind is that once you launched your thread there isn't many elegant ways to kill it. This means that it's better to set up a total_duration
variable rather than using while True
.
See code below:
import ipywidgets as widgets
import time
from IPython.display import display, clear_output
import threading
btn = widgets.Button(description = "Trigger")
pause = widgets.Checkbox(value = False, description = "Paused?")
number = widgets.Label("0")
wid = widgets.VBox([btn,number,pause])
display(wid)
def triggered(b):
number.value = str(int(number.value) - 1)
btn.on_click(triggered)
def counter(number,pause,total_duration):
for t in range(total_duration):
if not pause.value:
time.sleep(1)
number.value = str(int(number.value) 1)
elif pause.value:
time.sleep(3)
total_duration=60
thread = threading.Thread(target=counter, args=(number,pause,total_duration,))
thread.start()