I found most of what I needed in an old post - I can now save user input into a string and 'echo' each char to the screen at the location of a prompt like I want:
while (window.pollEvent(e)) {
if (e.type == Event::KeyPressed) {
if (e.type == Event::TextEntered) {
if (e.text.unicode < 128) {
input += static_cast<char>(e.text.unicode);
output.setFillColor(Color::White);
output.setString(input);
}
}
}
.
.
.
window.draw(prompt);
window.draw(output);
What I need now is a way to make the 'backspace' button work like it's supposed to. Will I have to manually pop a char off the end of the string for each "Keyboard::Backspace" detected, or does SFML have something for that?
I found most of what I needed in an old post - I can now save user input into a string and 'echo' each char to the screen at the location of a prompt like I want:
while (window.pollEvent(e)) {
if (e.type == Event::KeyPressed) {
if (e.type == Event::TextEntered) {
if (e.text.unicode < 128) {
input += static_cast<char>(e.text.unicode);
output.setFillColor(Color::White);
output.setString(input);
}
}
}
.
.
.
window.draw(prompt);
window.draw(output);
What I need now is a way to make the 'backspace' button work like it's supposed to. Will I have to manually pop a char off the end of the string for each "Keyboard::Backspace" detected, or does SFML have something for that?
If u have a std::string called input which u use to set the Text object, then u need to pop the last char from std::string. There is a fuction substr for std::string which will return a substring (basically u cut the string)
it quite easy to retrieve all ASCII characters programmatically, just run a for-loop to print out all characters that range from 0 to 255. unless i misunderstood what you are trying to achieve.
for (int i = 0; i < 255; i++)
std::cout << i << ' ' << (char)i << '\n';
The for-loop will tell you all information you need, the printable ASCII characters and its index position For example:If i run the for-loop in my PC it will print something like this:
30 �
31 �
32
33 !
34 "
35 #
36 $
37 %
........
122 z
123 {
124 |
125 }
126 ~
127
128 �
129 �
From the output, we can easily now detect all of printable chars and its indices which is clearly the printable chars start from index 32 upto 127. now, we need to add this boundary check to SFML event-loop:
//if (event.text.unicode >= 32 && event.text.unicode <= 127)
if (std::isprint(event.text.unicode)) // thanks to Laurent
input_text += event.text.unicode;
Don't worry about if user press BackSpace or Return/Enter keys, sf::Text will take care for these inputs internally, just supply the string to sf::Text::setString with escape char in event-loop:
if (event.key.code == sf::Keyboard::BackSpace) {
if (!input_text.empty())
input_text.pop_back();// as Laurent pointed out
//input_text.erase(--input_text.end());
}
if (event.key.code == sf::Keyboard::Return){
input_text += '\n';
}
That's it, we have accomplished a minimal text editor.
I added a simple blinking effect to “cursor”. It was a part of my early demos when I was working out with the SFML library. ;D
Here the complete source source:
#include <SFML/Graphics.hpp>
#include <locale>
int main()
{
sf::RenderWindow window({ 640 ,480 }, "test");
std::string input_text;
sf::Font font;
font.loadFromFile("resources/font.ttf");
sf::Text text("", font);
sf::Clock clock;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
else if (event.type == sf::Event::TextEntered) {
if (std::isprint(event.text.unicode))
input_text += event.text.unicode;
}
else if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::BackSpace) {
if (!input_text.empty())
input_text.pop_back();
}
if (event.key.code == sf::Keyboard::Return) {
input_text += '\n';
}
}
}
static sf::Time text_effect_time;
static bool show_cursor;
text_effect_time += clock.restart();
if (text_effect_time >= sf::seconds(0.5f))
{
show_cursor = !show_cursor;
text_effect_time = sf::Time::Zero;
}
text.setString(input_text + (show_cursor ? '_' : ' '));
window.clear();
window.draw(text);
window.display();
}
}