FTXUI
FTXUI copied to clipboard
Console doesn't clear previous renderer text after new renderer
When I select the menu first option, I get the both the current renderer's text "Now, please enter the server manager's address and port, so that you'll be able to see all the available public servers!" and the previous "Welcome, my client".
I tried using screen.Clear() too, and it didn't work.
#include <ftxui/component/component.hpp>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <ftxui/component/screen_interactive.hpp>
#include <iostream>
#include <array>
#include <string>
using namespace ftxui;
using namespace std;
enum class ConnectionMethod
{
ByName, ByAddress
};
void promptForConnectionMethod();
void promptForServerName();
void promptForServerAddress();
void promptForServerManager();
auto screen {
ScreenInteractive::TerminalOutput()
};
int main()
{
promptForConnectionMethod();
return 0;
}
void promptForConnectionMethod()
{
std::vector<std::string> conncet_choices {
"Connect by name...",
"Connect by address and port..."
};
int selected {0};
MenuOption option;
option.on_enter = screen.ExitLoopClosure();
auto connect_menu {
Menu(
&conncet_choices,
&selected,
option
)
};
auto renderer {
Renderer(
connect_menu,
[&]
{
return
center(
vbox(
center(text("Welcome, my client!") | color(Color::Red3Bis) | bold),
gauge(0), gauge(0),
text(
"Welcome to my first working multiplayer game, Medium Boxes."
)
| color(Color::LightSkyBlue1),
gauge(0),
center(
text("Now, choose how you'd prefer to connect to a server!")
| color(Color::LightCyan3)
),
gauge(0),
border(connect_menu->Render())
)
)
;
}
)
};
screen.Loop(renderer);
if(selected == 0)
{
promptForServerManager();
promptForServerName();
}
else
{
promptForServerAddress();
}
}
void promptForServerName()
{
}
void promptForServerAddress()
{
auto screen {
ScreenInteractive::TerminalOutput()
};
}
void promptForServerManager()
{
auto renderer {
Renderer(
[&]
{
return
center(
vbox(
text("Now, please enter the server manager's address and port, so that you'll be able to see all the available public servers!") | color(Color::LightGreenBis),
gauge(0)
)
)
;
}
)
};
screen.Loop(renderer);
}
Thanks!
I think this is the consequence of: https://github.com/ArthurSonzogni/FTXUI/blob/main/src/ftxui/component/screen_interactive.cpp#L544-L548
That is to say, after unwrapping the last screen, a new line is inserted at the end, so that the shell's command line starts below and do not override the previous frame.
In your case, there is a single Screen, where Loop
is called multiple time. So a new line is added each time.
I believe this is something we should improve.
In the meantime, I propose two alternatives:
1. Use "nested" screen.
That is to say, use different screen in each function, and call one function while executing the previous one.
code
#include <ftxui/component/component.hpp>
#include <ftxui/component/screen_interactive.hpp>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <array>
#include <iostream>
#include <string>
using namespace ftxui;
using namespace std;
enum class ConnectionMethod { ByName, ByAddress };
void promptForConnectionMethod();
void promptForServerName();
void promptForServerAddress();
void promptForServerManager();
int main() {
promptForConnectionMethod();
return 0;
}
void promptForConnectionMethod() {
auto screen = ScreenInteractive::TerminalOutput();
std::vector<std::string> connect_choice{
"Connect by name...",
"Connect by address and port...",
"Exit",
};
int selected = 0;
MenuOption option;
option.on_enter = [&] {
if (selected == 0) {
promptForServerManager();
} else if (selected == 1) {
promptForServerAddress();
} else if (selected == 2) {
screen.Exit();
}
};
auto connect_menu = Menu(&connect_choice, &selected, option);
auto renderer = Renderer(connect_menu, [&] {
return vbox({
text("Welcome, my client!") | color(Color::Red3Bis) | bold |
center,
text(""),
text("Selected = " + std::to_string(selected)) |
color(Color::LightGreenBis) | bold | center,
text(""),
text("Welcome to my first working multiplayer game, Medium "
"Boxes.") |
color(Color::LightSkyBlue1),
text(""),
text("Now, choose how you'd prefer to connect to a server!") |
color(Color::LightCyan3) | center,
text(""),
connect_menu->Render() | border,
}) |
center;
});
screen.Loop(renderer);
}
void promptForServerName() {}
void promptForServerAddress() {
auto screen = ScreenInteractive::TerminalOutput();
}
void promptForServerManager() {
auto screen = ScreenInteractive::TerminalOutput();
auto renderer = Renderer([&] {
return vbox({
text("Now, please enter the server manager's address and "
"port, so that you'll be able to see all the available "
"public servers!") |
color(Color::LightGreenBis),
gauge(0),
}) |
center;
});
screen.Loop(renderer);
}
2. Use the Tab
Create a "super" component that will regroup every "page" you want to display.
The "super" component will be a Tab({...pages}, &selected_page)
.
To display a different page, you will have to update the selected_page
integer.
@ArthurSonzogni Using nested screens doesn't seem to work, now I get the whole previous frame
Can confirm, I have the same bug.
The bug seems to be present in the Tab
container too when switching to a new tab. The screen isnt cleared after the first time the new tab is rendered.
For now I'm using a conditional to check whether the new "tab" has already been rendered to decide whether the program should render it again, and it seems to be working good