I am able to produce a window which has a widget (button) and a canvas which is ‘drawing’ a GR plot. The problem is that on display, calling the ‘draw’ function again, does not result in an updated plot. The button can listen for signals of “clicked” and that function handler can respond by calling the draw function, but that does not update the plot in the canvas. Now, if the window is resized the plot then updates and redraws/refreshes.
This code here displays the effect:
using Gtk.ShortNames, Gtk.GConstants
#counter to track the draw calls
global drawInt = 0
ctx = Gtk.getgc(widget)
ENV["GKS_WSTYPE"] = "142"
ENV["GKSconid"] = @sprintf("%lu", UInt64(ctx.ptr))
#random data to plot that gets shifted with every draw call
scatter( randn(100) .+ drawInt , rand(100) .+ drawInt )
drawInt += 1
println("in draw fn drawInt=$(drawInt)")
#put a canvas for the plot and a button
win = Window("Gtk") |> (bx = Box(:v))
canvas = Canvas(600, 450)
bt = Button("ok")
ctx = Gtk.getgc(canvas)
println("in button fn drawInt=$(drawInt)")
signal_connect(on_button_clicked, bt, "clicked")
canvas.draw = draw
There are some println statement so that the calls to the draw and button functions can be tracked as the canvas plot fails to update. Press the button multiple times to see the calls and updates to the global drawInt counter. Now, resize the window with the mouse, or click on another application window pane (eg browser) and you will see plot space update (the counter is a shift for the dummy data).
How can the update to the plot be performed without requiring a window pane event?
(from the Gtk3 developer guide something similar is stated-> https://developer.gnome.org/gtk3/stable/ch01s05.html, The contents of a widget often need to be partially or fully redrawn, e.g. when another window is moved and uncovers part of the widget, or when the window containing it is resized. It is also possible to explicitly cause part or all of the widget to be redrawn, by calling gtk_widget_queue_draw() or its variants. GTK+ takes care of most of the details by providing a ready-to-use cairo context to the ::draw signal handler)
I have run the code, and see the same effect as I have described. I don’t know if it runs differently on your system (I’m on Debian9), but the button registers the clicks, the function scopes appear to be running their inner statements, but the update to that red rectangle you put, does not appear until a window pane event/signal is received
that is with Cairo, and the goal is to have the ability to include figures from GR or Plots in general so that numerical investigations in a gui do not require ground up work from Cairo
I don’t know if it is the same on your system, but running your code multiple times shows that the drawing of the rescalled rectangle only occurs after a window pane event signal and not due to a widget event signal
As you imply, the canvas draw function is invoked by events like resizing the parent window,
so probably that is not where you should update the plot contents. Consider maintaining global buffers for data to be plotted, and have the draw function use that data, but otherwise as you have it above. The on_button_clicked method would then update the global data buffers, then force a redraw.
I am unsure how to do that within the Gtk.jl package. The Gtk3 developer guides at something along the lines of what you say with gtk_widget_queue_draw() but I don’t see how I can do that within Gtk.jl. Or can I access that global buffer with a direct call?
Did you run the example in an new julia session (include)? As there are already a list of functions with the name draw defined (in your code and in Gtk) this might lead to some ambiguity.
I remember having a similar problem and it was back then subject of ‘wrong’ binding of draw.
Gtk.draw(widget) calls reveal on the widget and that ccalls gtk_widget_queue_draw so it puts a signal into Gtk’s queue for redrawing. That’s actually the same way how the resize/uncover works.
Technically GR/Plots also renders with Cairo (as actually you cannot do anything else in GtkCanvas) - so you use the same interface.
After doing some more exploration I see the meaning of your sentence
"Technically GR/Plots also renders with Cairo (as actually you cannot do anything else in GtkCanvas) - so you use the same interface."
Question, would it maybe be a more flexible approach to consider the canvas widgets as regions for Cairo drawings? And somehow convert plots into Cairo drawings? Where maybe we go from a plot to imshow? Would that maybe be too slow? but it would avoid problems correct?
Someone else ran your code and it… did solve the problem as well; thanks alot*! I don’t know why it exhibited different behavior at first. The only thing is that the resizing still affects the size of the rectangle
I just used globals to make things visible to all methods. It would be much better to use a composite widget which includes all the needed data as properties; that would take more effort to design.
The const variables here are Ref types, and act like pointers so the vector content can be replaced. This pattern can help for efficiency and prevents some programmer error. This usage is not well documented, and should perhaps be discouraged since it’s not naturally thread-safe.
Although one could probably consolidate the functions, the separation simplifies the logic.