1

so I'm working with SFML here, and I basically want to make a string out of entered letters. SFML has a built in thing to check if keys are pressed inside of a window, and it also has one to detect if it is something specific like a backspace, so I wanted to combine these to make it so you could type and backspace a string (since without the backspace detection, it doesn't do anything if you press it).

Here's my code:

#include <iostream>
#include "SFML/Window.hpp"
#include <vector>

using namespace std;
using namespace sf;

int main() {
    // Initializes the class and creates the window
    Window window;
    window.create(VideoMode(800, 600), "Test window", Style::Close | Style::Titlebar | Style::Resize);
    // Run while the window is open
    vector <char> sentence;
    while (window.isOpen()) {
        Event event;
        // Check if an event is triggered
        while (window.pollEvent(event)) {
            // If the event is to close it, close it
            if (event.type == Event::Closed) {
                window.close();
            }
            // If the backspace key is pressed
            else if (event.type == Event::KeyPressed) {
                if (event.key.code == Keyboard::BackSpace) {
                    sentence.pop_back();
                }
            }
            // If text is entered in the window
            else if (event.type == Event::TextEntered) {
                sentence.push_back(static_cast <char> (event.text.unicode));
                cout << "Sentence = ";
                for (int i = 0; i < sentence.size(); i++) {
                    cout << sentence[i];
                }
                cout << endl;
            }
        }
    }
    return 0;
}

Basically, it creates a window, then it checks if it is closed, and then it checks if a backspace was pressed, and then it checks if a backspace wasn't pressed, but a different key was.

And so this all works great on my IDE (Visual Studio 2017 Community), however, when I press backspace more than once (it works the first time), it doesn't remove the character.

My assumption is that this is due to the event not clearing, but this wouldn't make sense since you can still do things like close the window after pressing backspace and such. Why does it only trigger the backspace if function once even though you press it multiple times?

1 Answers1

0

The backspace is also a character, even if it's invisible. As such when you press backspace it will remove the last character from the buffer and add an invisible character to the buffer.

Thus you have to ignore the backspace character on the TextEntered event. Additionally, you need a check for the pop, so you don't try to pop when there's no element.

Here's my update version of your code.

#include <iostream>
#include <SFML/Graphics.hpp>

void print_scentence(const std::vector<char>& sentence) {
    std::cout << "Sentence = ";
    for (auto c : sentence)
    {
        std::cout << c;
    }
    std::cout << "\n";
}

int main() {
    // Initializes the class and creates the window
    sf::Window window;
    window.create(sf::VideoMode(800, 600), "Test window", sf::Style::Close | sf::Style::Titlebar | sf::Style::Resize);
    // Run while the window is open
    std::vector<char> sentence;
    while (window.isOpen()) {
        sf::Event event;
        // Check if an event is triggered
        while (window.pollEvent(event)) {
            // If the event is to close it, close it
            if (event.type == sf::Event::Closed) {
                window.close();
            }
            // If the backspace key is pressed
            else if (event.type == sf::Event::KeyPressed) {
                if (event.key.code == sf::Keyboard::BackSpace && !sentence.empty()) {
                    sentence.pop_back();
                    print_scentence(sentence);
                }
            }
            // If text is entered in the window
            else if (event.type == sf::Event::TextEntered) {
                if (event.text.unicode == 8) {
                    continue;
                }

                sentence.push_back(static_cast<char>(event.text.unicode));
                print_scentence(sentence);
            }
        }
    }
}

As you can see from the code, I recommend to not use using namespace, use range-base for loop to iterate through a vector and use \n instead of std::endl, as you want a newline and not a forced flush as well.

Also, unless you're going to use OpenGL directly or use the window handle in an other way, you probably want to use sf::RenderWindow instead.

Lukas
  • 2,461
  • 2
  • 19
  • 32