# (Gtk.jl) Why does this MWE not produce an animation and only show the last updated draw call?

**URL:** <https://discourse.julialang.org/t/gtk-jl-why-does-this-mwe-not-produce-an-animation-and-only-show-the-last-updated-draw-call/27250>\
**Category:** General Usage\
**Created:** [August 7, 2019, 3:28am UTC](https://discourse.julialang.org/t/gtk-jl-why-does-this-mwe-not-produce-an-animation-and-only-show-the-last-updated-draw-call/27250 "2019-08-07T03:28:36Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mantzaris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mantzaris/32/3852_2.png) [@mantzaris](https://discourse.julialang.org/u/mantzaris)\
**Post date:** [August 7, 2019, 3:28am UTC](https://discourse.julialang.org/t/gtk-jl-why-does-this-mwe-not-produce-an-animation-and-only-show-the-last-updated-draw-call/27250/1 "2019-08-07T03:28:36Z")

</div>

Using `Gtk.jl` I would like to be able to produce an animation within a canvas widget. I have this MWE, which when run, produces a window with 2 buttons and a canvas. The first button each time pressed changes the canvas to present a rectangle of a randomly chosen color. The second button uses the `Timer` object to call a function _multiple times with a delay_ to again produce on the canvas a new random color, but there is strange behavior in that only the last iteration produces a visible change in the color. I have a println statement showing that the timer is calling the draw function multiple times, but only upon the final iteration is an effect seen. Is this to do with ‘double-buffering’? Is there a solution similar to plots with the `display(plt)` function? Is there a queue function to flush a stack?

```julia
using Gtk
using Cairo

global canvasWidget

function b_handler1(Widget)
    println("button1")
    global canvasWidget
    Gtk.draw(canvasWidget)
end
function b_handler2(Widget)
    println("button2")
    global canvasWidget

    Gtk.draw(canvasWidget)
    callFive(canvasWidget)
    
end

function callFive(canvasWidget)
    i=0
    cb(timer) = begin
        (Gtk.draw(canvasWidget))
        i+=1
        println("i=$(i)")
    end
    t = Timer(cb, 1, interval=0.5)
    wait(t)
    sleep(5)
    close(t)
    
end

function drawColor(Widget)
    println("color")
    ctx = getgc(Widget)
    h = height(Widget)
    w = width(Widget)
    rectangle(ctx, 0, 0, w, h)
    set_source_rgb(ctx, rand(), rand(), rand())
    fill(ctx)
end
win = Gtk.Window("random colors")

boxV = Gtk.Box(:v)
push!(win,boxV)

button1 = Gtk.Button("change color once")
button2 = Gtk.Button("change color 5x")

signal_connect(b_handler1,button1, "clicked")
signal_connect(b_handler2,button2, "clicked")

push!(boxV,button1)
push!(boxV,button2)

canvasWidget = Gtk.Canvas(200,200)
canvasWidget.draw = drawColor
push!(boxV,canvasWidget)

Gtk.showall(win)

```

Running this code (self contained) should display the effect I am referring to with the second button, which I would like to run for 5 seconds, and update the colors every half a second.

This recent post by @tobias.knopp, `https://discourse.julialang.org/t/threading-1-3-success-story/27111`, shows an updating bar by utilizing the new threads capabilities in Julia1.3

```julia
signal_connect(button, "clicked") do widget
  Threads.@spawn doWork()
end

```

Would upgrading let me use this to solve the task, or is there another approach that can be used to update upon each draw call?

---

<div class="post-metadata">

**Author:** ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)\
**Post date:** [August 7, 2019, 9:54pm UTC](https://discourse.julialang.org/t/gtk-jl-why-does-this-mwe-not-produce-an-animation-and-only-show-the-last-updated-draw-call/27250/2 "2019-08-07T21:54:20Z")

</div>

Hi @mantzaris,

this is doable without threading. Just change your draw function with

```julia
function callFive(canvasWidget)
    i=0
    t0 = now()
    function cb(timer)
        Gtk.draw(canvasWidget)
        
        i+=1
        println("i=$(i)")

        if (now()-t0).value > 5000
          close(timer)
        end
    end
    t = Timer(cb, 1, interval=0.5)
end

```

The essential point here is that you need to leave the callback so that Gtk can draw again. In your original code the entire UI is frozen until you left the callback.

Using this pattern, I have successfully developed some async applications. This works well in case your callbacks are fast. Background threads can be simulated by repeatedly sleeping, so that the UI can be redrawn.

---

<div class="post-metadata">

**Author:** ![mantzaris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mantzaris/32/3852_2.png) [@mantzaris](https://discourse.julialang.org/u/mantzaris)\
**Post date:** [August 7, 2019, 10:20pm UTC](https://discourse.julialang.org/t/gtk-jl-why-does-this-mwe-not-produce-an-animation-and-only-show-the-last-updated-draw-call/27250/3 "2019-08-07T22:20:58Z")

</div>

> [@tobias.knopp](#):
>
> 1-The essential point here is that you need to leave the callback so that Gtk can draw again.
> 
> 2- Background threads can be simulated by repeatedly sleeping, so that the UI can be redrawn.

Thank you, this worked! It is great to see it operate.

1)so the callback leaving must be explicitly done from what I understand. Is there another route where a `Timer` is not used? I cannot find a route that does not use it.

1. I have tried using sleep as well, and not found how it can be used  
eg. `sleep(1); close(timer)` does not work.

---

<div class="post-metadata">

**Author:** ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)\
**Post date:** [August 8, 2019, 8:03am UTC](https://discourse.julialang.org/t/gtk-jl-why-does-this-mwe-not-produce-an-animation-and-only-show-the-last-updated-draw-call/27250/4 "2019-08-08T08:03:20Z")

</div>

A Timer is not necessary, but a Task is. Here is a more advanced solution that I use in some real code

```julia
using Gtk
using Dates

global canvasWidget
global state 

mutable struct CallbackState
  task::Union{Task,Nothing}
  cancelled::Bool
  startTime::DateTime
  canvas::GtkCanvas
end

function cancel(state::CallbackState)
  measState.cancelled = true
end

function callback(canvasWidget)
  state = CallbackState(nothing, false, now(), canvasWidget)
  state.task = Task(()->callbackInner(state))
  schedule(state.task)
  return state
end

function callbackInner(state::CallbackState)
    i = 0
    while !state.cancelled
        Gtk.draw(state.canvas)
        
        i+=1
        println("i=$(i)")

        if (now() - state.startTime).value > 10000
          state.cancelled = true
        end
        sleep(0.5)
    end
end

function drawColor(Widget)
    println("color")
    ctx = getgc(Widget)
    h = height(Widget)
    w = width(Widget)
    rectangle(ctx, 0, 0, w, h)
    set_source_rgb(ctx, rand(), rand(), rand())
    fill(ctx)
end

win = Gtk.Window("random colors")

boxV = Gtk.Box(:v)
push!(win,boxV)

button1 = Gtk.Button("change color 5x")
button2 = Gtk.Button("cancel")

function b_handler1(widget)
    println("button1")
    global canvasWidget
    global state
    state = callback(canvasWidget)
end

function b_handler2(widget)
    global state
    state.cancelled = true
end

signal_connect(b_handler1, button1, "clicked")
signal_connect(b_handler2, button2, "clicked")

push!(boxV,button1)
push!(boxV,button2)

canvasWidget = Gtk.Canvas(200,200)
canvasWidget.draw = drawColor
push!(boxV, canvasWidget)

Gtk.showall(win)

```

It allows you to spawn a Task and communicate with it using a struct. As an example I have implemented a cancel button to stop the task. In real code one should wrap the globals into a `Ref` so that things keep typestable.

---

<div class="post-metadata">

**Author:** ![mantzaris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mantzaris/32/3852_2.png) [@mantzaris](https://discourse.julialang.org/u/mantzaris)\
**Post date:** [August 8, 2019, 11:54pm UTC](https://discourse.julialang.org/t/gtk-jl-why-does-this-mwe-not-produce-an-animation-and-only-show-the-last-updated-draw-call/27250/5 "2019-08-08T23:54:56Z")

</div>

> [@tobias.knopp](#):
>
> state.task = Task(()-\>callbackInner(state)) schedule(state.task)

So the `Task` here still runs in a thread of its own? And how does the `schedule(state.task)` allow the Gtk.draw(state.canvas) to occur in a loop and not become _frozen_ on its own even if the rest of the UI is not locked up on that thread?

It is interesting how you now can pass arguments to the `Task` function callback which in the docs does not allow for arguments to be passed: `Task(()->callbackInner(state)`. The syntax, means that there is a lambda associated with that function call to `Task`?

---

<div class="post-metadata">

**Author:** ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)\
**Post date:** [August 9, 2019, 7:16am UTC](https://discourse.julialang.org/t/gtk-jl-why-does-this-mwe-not-produce-an-animation-and-only-show-the-last-updated-draw-call/27250/6 "2019-08-09T07:16:25Z")

</div>

> [@mantzaris](#):
>
> So the `Task` here still runs in a thread of its own?

It does not run on a thread but on a Task, which currently is a so-called “green-thread”. Green threads are running all on the same thread and are cooperating with each other by yielding, which means they need to go sleeping from time to time.

> [@mantzaris](#):
>
> And how does the `schedule(state.task)` allow the Gtk.draw(state.canvas) to occur in a loop and not become _frozen_ on its own even if the rest of the UI is not locked up on that thread?

schedule actually just says that the Task can be started but it will not do so immediately. You can have a look at the manual where `@async` is described. What I am doing here is the same but the Task creation is not hidden in a macro.

> [@mantzaris](#):
>
> It is interesting how you now can pass arguments to the `Task` function callback which in the docs does not allow for arguments to be passed: `Task(()->callbackInner(state)` . The syntax, means that there is a lambda associated with that function call to `Task` ?

Yes, Task wants a function without arguments. `() ->callbackInner(state)` creates such a function. You can also write `tmp_func() = callbackInner(state)` and pass that to the Task.
