How to update view from thread? #211
Answered
by
MattBystrin
matthesoundman
asked this question in
Q&A
-
Hello @ArthurSonzogni, How can I update view from a thread that is producing strings that I want the view to then show? I tried it out it only updates when I toggle between buttons in my view. I started out with something that just performs an Any suggestions or tips on how to improve this setup? Here is code: #include <ftxui/component/screen_interactive.hpp>
#include <ftxui/component/component.hpp>
#include <array>
#include <chrono>
using namespace ftxui;
using namespace std::chrono_literals;
#pragma mark LAYER
enum Layer {
welcome_layer,
settings_layer,
stream_layer
};
#pragma mark START STREAM
void start_stream(std::thread& stream_thread, Component& stream_container) {
auto cmd {"while true; do echo 'hello from thread'; sleep 1; done;"};
stream_thread = std::thread([&]() {
std::array<char, 128> buffer;
std::string result;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (not pipe) { throw std::runtime_error("popen() failed!"); }
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
if (result.back() == '\n') {
stream_container.get()->Add(MenuEntry(result));
result = "";
buffer.fill(0);
}
}
});
stream_thread.detach();
}
void stop_stream(std::thread& stream_thread) {}
#pragma mark MAIN
int main() {
int active_layer {Layer::welcome_layer};
#pragma mark WELCOME LAYER
constexpr auto welcome_label {L"Welcome to ..."};
auto welcome_layer_container {Container::Vertical({
Button("Start", nullptr),
Button("Settings", [&] { active_layer = Layer::settings_layer; }),
Button("Log Stream", [&] { active_layer = Layer::stream_layer; })
})};
auto welcome_renderer {Renderer(welcome_layer_container, [&] {
return vbox({
hcenter(bold(text(welcome_label))),
separator(),
welcome_layer_container->Render() | center
});
})};
#pragma mark SETTINGS LAYER
constexpr auto settings_label {L"Settings"};
auto settings_layer_container {Container::Vertical({
Container::Horizontal({
Button("Back", [&] { active_layer = Layer::welcome_layer; })
}),
})};
auto settings_renderer {Renderer(settings_layer_container, [&] {
return vbox({
hcenter(bold(text(settings_label))),
separator(),
settings_layer_container->Render() | center
});
})};
#pragma mark LOG STREAM LAYER
std::thread log_thread;
constexpr auto log_stream_label {L"Log Stream"};
auto log_messages_container {Container::Vertical({})};
auto log_messages_renderer {Renderer(log_messages_container, [&] {
return vbox({ log_messages_container->Render() | frame | border | flex });
})};
auto log_stream_layer_container {Container::Horizontal({
Button("Back", [&] { active_layer = Layer::welcome_layer; }),
Button("Start Stream", [&] { start_stream(log_thread, log_messages_container); }),
Button("Stop Stream", [&] { stop_stream(log_thread); })
})};
auto log_stream_renderer {Renderer(log_stream_layer_container, [&] {
return vbox({
hcenter(bold(text(log_stream_label))),
separator(),
log_stream_layer_container->Render() | center
});
})};
auto log_stream_view {Container::Vertical({
log_stream_renderer,
log_messages_renderer
})};
#pragma mark LAYER CONTAINER
auto layer_container {Container::Tab({
welcome_renderer,
settings_renderer,
log_stream_view
}, &active_layer)};
#pragma mark MAIN_RENDERER
auto main_renderer {Renderer(layer_container, [&] {
switch (active_layer) {
case Layer::welcome_layer:
return welcome_renderer->Render();
case Layer::settings_layer:
return settings_renderer->Render();
case Layer::stream_layer:
return log_stream_view->Render();
default:
return welcome_renderer->Render();
}
})};
#pragma mark RUN
auto screen {ScreenInteractive::Fullscreen()};
screen.Loop(main_renderer);
return 0;
} Thanks. |
Beta Was this translation helpful? Give feedback.
Answered by
MattBystrin
Sep 21, 2021
Replies: 1 comment 9 replies
-
Hello , @matthesoundman ! Have you tried to call |
Beta Was this translation helpful? Give feedback.
9 replies
Answer selected by
matthesoundman
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello , @matthesoundman ! Have you tried to call
screen.PostEvent(Event::Custom)
to update your UI ?