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
endand 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
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Loading packages
Before reading this short tutorial, it's highly recommended to take a glance at
Renderer.jlto 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
arrat160by runningarr[160] = 2in REPL, then you can see the UI gets updated immediately. No magic, crystal clear, just global variables.Infinite Loop
In practice, the data
arris 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 usingTasks.First, we define a
stop_flagfor exiting the function manually. Then, we define a simple functionupdate!for manipulating the content ofarr.The
infinite_loopfunction 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-yieldpairs.To invoke the function, we firstly make sure the
stop_flagis set tofalse, then callinfinite_loop:Now, you can see the animation in the UI window. To stop the task, set
stop_flagtotrue.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
arrand a hookstop_flagcontrolling 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 = trueto set the value in REPL. That's redundant, our UI needs to be improved! Let's add aCheckboxfor controlling this state. To edit UI, we only need to tweak theuifunction, 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