So my latest attempt is the following. I use two flags, one to trigger start an the other to trigger stop. Is that the kind of logic you had in mind ?
I also limited the number of runnable tasks by watching the animate button click count.
function plot_random_with_button()
x = Observable(rand(10))
y = Observable(rand(10))
f = Figure()
ax = Axis(f[1, 1])
p = plot!(x, y)
buta = Button(f[2, :], label="Animate", tellwidth=false)
buts = Button(f[3, :], label="Stop", tellwidth=false)
onflag = Observable(false)
offflag = Observable(true)
on(buta.clicks, priority=1) do c
if c == 1
onflag.val = true
@async while onflag.val
x[] = rand(10)
y[] = rand(10)
sleep(0.1)
offflag.val == true && break
end
offflag.val = false
end
Consume(true)
end
on(buts.clicks, priority=2) do _
offflag.val = true
buta.clicks = 0
end
return f
end
@attdona Thanks for the tip about Visor
! I think it’s a bit much for what I’m working on right now, but I have another project that could really benefit from this.
EDIT I’ve tried coupling the former solution with a slider and set_close_to!
but there is something weird. Two clicks on the Stop
button are required while from the code, I would have expected only one to suffice. Do you have a recommendation about this behavior ?
function plot_random_with_button()
f = Figure()
ax = Axis(f[1, 1])
buta = Button(f[2, :], label="Animate", tellwidth=false)
buts = Button(f[3, :], label="Stop", tellwidth=false)
sl = Slider(f[4, :], range=range(0, 2 * pi, 50))
x = Observable(range(0, 2 * pi, 100))
y = lift(x, sl.value) do x, p
cos.(x .+ p)
end
p = plot!(x, y)
onflag = Observable(false)
offflag = Observable(true)
on(buta.clicks, priority=1) do c
if c == 1
onflag.val = true
@async for val in Iterators.cycle(sl.range[])
sleep(1 / 30)
set_close_to!(sl, val)
offflag.val == true && break
end
offflag.val = false
end
Consume(true)
end
on(buts.clicks, priority=2) do _
offflag.val = true
set_close_to!(sl, 0)
buta.clicks = 0
Consume(true)
end
f
end
After one click
After two clicks