How to do simple state-management with pure CImGui #39
Gnimuc
started this conversation in
Show and tell
Replies: 2 comments 2 replies
-
How would I update values in the state based on widget inputs? For example I tried adding to the state: mutable struct MyStates
arr::Vector{Cfloat}
is_stop::Bool
afloat::Cfloat
end and tried to use a slider to modify it: CImGui.SliderFloat("slider float", Ref(state.afloat), 0.0, 1.0, "ratio = %.3f") However after I change the slider it just snaps right back to 0.0, and the state value isn't updated. |
Beta Was this translation helpful? Give feedback.
2 replies
-
Just rewrote this example to work with ImPlot demo: |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Loading packages
Before reading this short tutorial, it's highly recommended to take a glance at
Renderer.jl
to at least get an idea about the fact that therender()
function is running asynchronously.Global variables
Let's start with a simple UI that only plots a sine wave.
Copy-paste the snippet into REPL to create the simple UI.
Now, put the UI window and REPL side-by-side and edit the global variable
arr
at160
by runningarr[160] = 2
in REPL, then you can see the UI gets updated immediately. No magic, crystal clear, just global variables.Infinite Loop
In practice, the data
arr
is very likely to be updated by another function and there might be an infinite loop inside that function. How could we handle that? The short answer is usingTask
s.First, we define a
stop_flag
for exiting the function manually. Then, we define a simple functionupdate!
for manipulating the content ofarr
.The
infinite_loop
function looks like this:It's as simple as an infinite while loop that is going to be scheduled asynchronously and run concurrently by using
@async-yield
pairs.To invoke the function, we firstly make sure the
stop_flag
is set tofalse
, then callinfinite_loop
:Now, you can see the animation in the UI window. To stop the task, set
stop_flag
totrue
.Mutable struct as state holder
For simple UIs, it's convenient to use global variables for state-management, but things get exaggerated every quickly as the UI states grow. It's better to integrate all of the global variables into a big global state instead of using separated global variables.
As of the above example, the UI has two meaningful states: a data container
arr
and a hookstop_flag
controlling when to exit theinfinite_loop
. So our state holder can look something like this:Now, we can rewrite the whole example as:
An example of interactive development
In the example above, we need to run
state_holder.is_stop = true
to set the value in REPL. That's redundant, our UI needs to be improved! Let's add aCheckbox
for controlling this state. To edit UI, we only need to tweak theui
function, that's the design. Functions should be decoupled from each other.Note that directly copy-pasting the code below when the UI is running will not trigger any updates. We need to close the UI windows and run Renderer.render again. Hot-loading UI can be done using Revise.jl, but that's beyond the scope of this post.
That's it.
Beta Was this translation helpful? Give feedback.
All reactions