QML.jl icon indicating copy to clipboard operation
QML.jl copied to clipboard

Using multiple JuliaCanvas'es

Open a-ill opened this issue 4 years ago • 6 comments

Is there a way to have multiple JuliaCanvas'es displaying different content? It seems that if I update one of them, then others also get updated.

a-ill avatar Dec 03 '20 12:12 a-ill

I have added an example for this here: https://github.com/barche/QML.jl/blob/master/example/canvas_twice.jl

You should use a separate callback function for each canvas.

barche avatar Dec 28 '20 00:12 barche

Hello I just couldn't figure out how to have a list (or even a dynamic list) of canvases. For example, I would need a set of canvases with circles of different radii (with a set of corresponding sliders). What would be a decent way to do that?

I have added an example for this here: https://github.com/barche/QML.jl/blob/master/example/canvas_twice.jl

You should use a separate callback function for each canvas.

belliavesha avatar Jan 15 '21 19:01 belliavesha

I just couldn't figure out how to have a list (or even a dynamic list) of canvases. For example, I would need a set of canvases with circles of different radii (with a set of corresponding sliders). What would be a decent way to do that?

You can use any QML component that takes a listmodel, and store the parameters for the canvas in a ListModel. The gltriangle example is also based on this, it uses a Repeater that takes a listmodel with the triangle corners, and represents each corner using a Rectangle "delegate" as it's called in QML. So you could create delegates that contain a JuliaCanvas, and then it should work. For the gltriangle example, the delegate is defined here:

https://github.com/barche/QML.jl/blob/0f03c09e43b161069b9bd53f07fb365ac90add38/example/qml/gltriangle.qml#L23-L57

barche avatar Jan 15 '21 22:01 barche

I tried to do that, but each JuliaCanvas must have its own paintFunction. I couldn't manage to create callback functions in a loop. safe_cfunction macro claims, that paint_canvas is not defined. My code Julia code is something like that.

mutable struct Circle
    number::Int
    radius::Float64
    render_function::CxxWrap.CxxWrapCore.SafeCFunction
end

circles = Circle[]
N = 5

function paint_nth_canvas(buffer, n)
    ...
end

for n in 1:N
    function paint_canvas(buffer::Array{UInt32, 1},
            width32::Int32,
            height32::Int32)
        width::Int = width32
        height::Int = height32
        buffer = reshape(buffer, width, height)
        buffer = reinterpret(ARGB32, buffer)
        paint_nth_canvas(buffer,i)
    end
    paint_canvas_wrapped = @safe_cfunction(paint_canvas, Cvoid, (Array{UInt32,1}, Int32, Int32))    
    push!(circles, Circle(i, 10.5*i^2 , paint_canvas_wrapped) )
end

circleModel = ListModel(circles)

belliavesha avatar Jan 16 '21 16:01 belliavesha

You need to add a $ before the function name in the @safe_cfunction call, but this fails due to a bug in CxxWrap, should be fixed with https://github.com/JuliaInterop/CxxWrap.jl/pull/282 but let's wait for the tests to pass :)

barche avatar Jan 19 '21 00:01 barche

OK, updating CxxWrap to version v0.11.2 and adding the $ like this should fix it:

paint_canvas_wrapped = @safe_cfunction($paint_canvas, Cvoid, (Array{UInt32,1}, Int32, Int32))

See the @cfunction macro docs for info on why the $ is needed.

barche avatar Jan 19 '21 15:01 barche