EditBox acts strange.

Started by krolik, 06 January 2019, 23:28:02

krolik

Hello!
I'm making a game using sfml + tgui, and for my level creator I need EditBoxes, so I made new tgui::Gui object for creator menu and loaded Widgets using loadWidgetsFromFile() function.
These Widget declarations in .txt file look like this:
Code (cpp) Select

EditBox.width {
    Position = (10, 40);
    DefaultText = "Number of cols...";
}

then, when in main menu I click button directing me to creator I'm calling this function in a loop:
Code (cpp) Select
void Menu::showEdit(sf::Event & event)
{
if (event.type == sf::Event::Closed)
window.close();
window.clear(sf::Color::White); // clear window with white color
editGui.handleEvent(event);
editGui.draw(); // drawing loaded widgets
window.display();
}

But with this code it doesn't work like it should, when I press any key loop manages to execute few times and I get a few characters instead of one, in addition, backspace doesn't work. I think I should change something in EditBok drawing, but I have run out of ideas, nothing seems to work so far. Could you give me some advice? I'm using TGUI 0.8. Thanks in advance :)

texus

You should probably restructure your code. Clearing and drawing shouldn't happen in the event loop. You should also pass all events to editGui.handleEvent, not just TextEntered ones. This is likely why backspace doesn't work, it relies on KeyPressed.
If showEdit is being called multiple times then the issue must be in the code where you are calling it.

There are probably many ways to redesign the code, here is one:
You should try to only have a single main loop which handles events and draws to the screen. Depending on the state of your program (e.g. whether in main menu or somewhere else), you call a different function for handling the event and for drawing (e.g. you use a pointer to a State class that has virtual handleEvent and draw functions). You can choose to either give each state its own Gui object or just have a single Gui object that you use everywhere and just put every screen in a Group (or Panel) and just show and hide this group when switch state.

krolik

Thanks! I managed to pull this off. Didn't need to change much tho, I had gameState variable, which changed depending on where I am in the game, my game loop has only switch instruction on current gameState:
Code (cpp) Select
while (window.isOpen())
{
sf::Event event;
switch (menu.getGameState())
{
case 0:
menu.showMenu(event);
break;
case 1:
std::cout << "LvlChoose" << std::endl;
break;
case 2:
menu.showEdit(event);
break;
case 3:
std::cout << "Play" << std::endl;
break;
case 4:
std::cout << "Auto" << std::endl;
break;
case 5:
menu.showAbout(event);
break;
}
}

And I changed fuctions to look like this:
Code (cpp) Select
void Menu::showEdit(sf::Event & event)
{
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
editGui.handleEvent(event);
}
window.clear(sf::Color::White); // clear window with white color
editGui.draw();
window.display();
}

I think I actually tried that before, but I must've made some mistake along the way. Thanks again :)