Dynamically adding elements to Checkboxes
dr-mrsthemonarch opened this issue · 5 comments
I'm working on a hardware controller emulator, which has UDP, and TCPServer elements, basically when a remote client connects to this controller, they should be able to send it commands, and the device will respond over a network, this works great. It's possible for multiple clients to connect, and interact with it, like the real thing.
I can start the servers, display responses, connections of clients, etc, like so
This server was developed so I can in actuality develop the client, of which I also want to use FTXUI. The client and server both need to add and remove found controllers/clients on the network.
Unfortunately, I have two issues that happen, either the container stays empty, and never updates dynamically the elements as they are pushed back to it ( I guess because this needs to be done at runtime?) or the entire program crashes when I start the TCPserver with a segmentation fault, or odd random text showing up.
My initial code of the checkbox being:
std::array<bool, 10> states;
auto checkboxes = Container::Vertical({});
for (int i = 0; i < clientVec.vec.size(); ++i) {
states[i] = false;
checkboxes->Add(Checkbox(clientVec.vec[i],
&states[i]) );
}
Component checkframe = Renderer(checkboxes, [&] {
return checkboxes->Render() | vscroll_indicator | frame |
size(HEIGHT, LESS_THAN, 5) | border | color(Color::Default);
});
checkframe=Wrap("To be Done",checkframe);
and the relevent code for the starting of the loop:
// -- Layout -----------------------------------------------------------------
auto layout = Container::Vertical({
checkframe,
// toggle,
input_add,
udpbuttons,
tcpbuttons
}) | size(HEIGHT, GREATER_THAN, 40);
auto component = Renderer(layout, [&] {
return vbox({
checkframe->Render(),
separator() | color(Color::Default),
udpbuttons->Render(),
separator() | color(Color::Default),
tcpbuttons->Render()
}) | size(WIDTH, GREATER_THAN, 30) | borderStyled(ROUNDED,Color::Default);
});
auto topwindows = Container::Horizontal({
component,
output | yflex,
});
auto layoutmain = Container::Vertical({
topwindows,
cliArea | flex,
});
auto renderer = Renderer(layoutmain, [&] {
return layoutmain->Render() ;
}); //main render for the entire interface.
//create a new thread to run the output continously/force redraw. Required for the output window to update on it's own instead of waiting for an event.
auto screenRedraw = std::thread([&](){
while(running){
screen.PostEvent(ftxui::Event::Custom);
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Prevent High CPU Usage.
}
});
screen.Loop(renderer);
screenRedraw.join();
}
I had assumed that when I constantly redraw the the screen on a seperate thread, it would update the client list, as things changed, but it remains empty unfortuantely.
clientVec.vec is a structure like so to ensure thread safety, if you're curious.
struct SharedVector {
std::vector<std::string> vec;
std::mutex vecMutex;
};
and I have a server class that pushes back entries when clients connect to clientVec.vec, that the checkbox should read from.
Is it possible to dynamically add elements/children to checkmarks like this?
Is it possible to dynamically add elements/children to checkmarks like this?
Yes it is possible.
I will take a look later today.
Maybe you can upload a video or a terminal record reproducing what you are seeing? In particular the crash?
Absolutely. It is random generally, but I happened to capture it in the first try. Usually it happens immediately, but in this case, it took some tries.
You can find the source code here: source If you want to look further in depth of my implementation, beyond the code I posted here.
and here is the recording. terminal record
Here's a link to the asciinema to play it, if the above recording doesn't work correctly:
[recording](
the animator)