Closed phuongnd08 closed 1 year ago
You are using scrolling_area
instead of area
, but the same solution applies.
Here is a working code sample with stable paths:
require 'glimmer-dsl-libui'
include Glimmer
window('Circle Random Coloring by Clicking', 400, 400) {
scrolling_area {
circle(200, 200, 90) { |c| # declarative stable path (implicit path syntax for a single shape nested directly under area)
fill r: 202, g: 102, b: 204, a: 0.5
stroke r: 0, g: 0, b: 0, thickness: 2
on_mouse_up do
c.fill = [rand(255), rand(255), rand(255)]
end
}
}
}.show
Here is the example re-written with dynamic paths:
require 'glimmer-dsl-libui'
include Glimmer
window('Circle Random Coloring by Clicking', 400, 400) {
@area = scrolling_area {
on_draw do |area_draw_params|
@circle = circle(200, 200, 90) { |c| # declarative stable path (implicit path syntax for a single shape nested directly under area)
fill r: rand(255), g: rand(255), b: rand(255), a: 0.5
stroke r: 0, g: 0, b: 0, thickness: 2
}
end
on_mouse_up do |mouse_event|
@area.queue_redraw_all if @circle.contain?(mouse_event[:x], mouse_event[:y])
end
}
}.show
https://github.com/AndyObtiva/glimmer-dsl-libui/assets/23052/28afcf86-f972-427a-9f46-6ee439bf11fd
Please let me know if either example's code helps you resolve your issue.
OK, I think I found the culprit in your code from https://github.com/AndyObtiva/glimmer-dsl-libui/issues/49:
scrolling_area {
text {
indicator = string
controller.on_stat_updated do |controller|
indicator.string = controller.indication
end
}
color_indicator = nil
color_area = area {
color_indicator = circle(200, 200, 90) { # declarative stable path (implicit path syntax for a single shape nested directly under area)
stroke r: 0, g: 0, b: 0, thickness: 2
fill <= controller.color
}
}
You are nesting an area {
within a scrolling_area {
! That's wrong! You must choose to either use an area
or a scrolling_area
. There is no need to nest an area
inside scrolling_area
, so you can nest the circle
directly under scrolling_area
, and that should resolve your issue.
Please confirm if the issue goes away once you apply this solution so that I'd close the issue.
okay, so I can see that if I use mouse_up to set the color, it's effective. if I call code from a thread, it's not effective.
Here is the code:
circle(200, 200, 90) do |color_indicator| # declarative stable path (implicit path syntax for a single shape nested directly under area)
stroke r: 0, g: 0, b: 0, thickness: 2
fill controller.color
on_mouse_up do
color_indicator.fill = [rand(255), rand(255), rand(255)]
end
Thread.new {
loop do
puts "fill with random color"
color_indicator.fill = [rand(255), rand(255), rand(255)]
sleep 1
end
}
end
if things run correctly, I am supposed to see a new color whenever I click on the circle, or every seconds. But I only see new color when I click on the circle. There are log in the terminal confirming the thread is running:
fill with random color
fill with random color
fill with random color
fill with random color
fill with random color
fill with random color
fill with random color
fill with random color
Adding queue_redraw_all doesn't help:
circle(200, 200, 90) do |color_indicator| # declarative stable path (implicit path syntax for a single shape nested directly under area)
stroke r: 0, g: 0, b: 0, thickness: 2
fill controller.color
on_mouse_up do
color_indicator.fill = [rand(255), rand(255), rand(255)]
end
Thread.new {
loop do
puts "fill with random color"
color_indicator.fill = [rand(255), rand(255), rand(255)]
@area&.queue_redraw_all
sleep 1
end
}
end
Yes, that's because if you're updating from a different Thread, you have to wrap all your calls to the GUI with Glimmer::LibUI.queue_main { ... }
in order to access the main GUI thread (documented under LibUI Operations and used in Glimmer Meta-Example). Also, you don't need area.queue_redraw_all
if you are using stable paths (e.g. nesting circle
directly under area
or scrolling_area
).
This updated sample updates the circle
fill
color from a Thread
(it also demonstrates the new recommended way of building Glimmer DSL for LibUI applications by taking advantage of the Glimmer::LibUI::Application
mixin (albeit optional), which provides a .launch
method and before_body
/after_body
hooks that execute before and after building the GUI body
):
require 'glimmer-dsl-libui'
include Glimmer
class CircleRandomColoringByThread
include Glimmer::LibUI::Application
after_body do
Thread.new {
loop do
puts "fill with random color"
Glimmer::LibUI.queue_main do
@circle.fill = [rand(255), rand(255), rand(255)]
end
sleep 1
end
}
end
body {
window('Circle Random Coloring by Clicking', 400, 400) {
scrolling_area {
@circle = circle(200, 200, 90) { |c| # declarative stable path (implicit path syntax for a single shape nested directly under area)
fill r: 202, g: 102, b: 204, a: 0.5
stroke r: 0, g: 0, b: 0, thickness: 2
on_mouse_up do
c.fill = [rand(255), rand(255), rand(255)]
end
}
}
}
}
end
CircleRandomColoringByThread.launch
If you are updating indirectly through a model/controller, you still have to wrap the update call to the model/controller (e.g. color_indicator.fill = [rand(255), rand(255), rand(255)]
) with Glimmer::LibUI.queue_main { ... }
:
Thread.new {
loop do
puts "fill with random color"
Glimmer::LibUI.queue_main do
color_indicator.fill = [rand(255), rand(255), rand(255)]
end
sleep 1
end
}
Please confirm if this resolves your issue in order to close it.
Cheers.
Thanks, my bad for not reading through the documentation. Though, my thought is either recommend every UI update to go through something link update_ui
block (i.e update_ui { code }
), and update_ui
is an alias of queue_main
under the hook, or design the library so that every GUI element attribute update automatically use queue_main as a convention so developer don't have to worry about this in their code. If this has a performance penalty, allow the developer to config this to not be a default behavior to speed up the app if they intend to do something seriously with it later?
Yeah, I actually automated this requirement completely in Glimmer DSL for SWT, which has an equivalent to queue_main called async_exec. After a certain version release, developers don’t need to use async_exec explicitly in Glimmer DSL for SWT anymore when running from a different thread. It happens automatically for them.
I will consider similarly automating the use of queue_main from other threads in Glimmwr DSL for LibUI. The library is relatively new, so I didn’t get a chance to do it. I’m adding this task to the TODO list.
Otherwise, I am closing this issue. If you have further comments or questions, feel free to reply. I will see your comments even if the issue is closed.
I couldn't re-open an issue that I think unsolved, so link it here for attention: https://github.com/AndyObtiva/glimmer-dsl-libui/issues/49