Good evening guys,
I found a bug with sf::Thread and sf::Text. It's a known bug, because I also found some topics about it, but they didn't help me out with my problem. ( http://en.sfml-dev.org/forums/index.php?topic=7730.0 (http://en.sfml-dev.org/forums/index.php?topic=7730.0) or http://en.sfml-dev.org/forums/index.php?topic=2073.0 (http://en.sfml-dev.org/forums/index.php?topic=2073.0) )
To the problem:
I made a chat, where the messages are shown in the window. But in nearly every message some letters are missing, or kinda buggy :/ The strange thing is, when I (or someone else) write more messages, the older messages slowly fill up (sometimes immediately): (Some pictures for better illustration) (I come from Austria, so its in german ;), but you can see it quite good I guess)
(https://dl.dropbox.com/u/8088302/Before.png) (https://dl.dropbox.com/u/8088302/After.png) (https://dl.dropbox.com/u/8088302/Bug.PNG)
I also found out that this happens, when sf::Text is made in a sf::Thread and rendered in the main thread. The text is in a std::list and i have a sf::Thread in one class. I also wrote a simple program that pruduces the bug for me (thats the important part) (writeData is the threadfunction):
void Chat::render()
{
for(iText=textList.begin(); iText!=textList.end(); ++iText)
window.draw((*iText));
}
void Chat::writeData()
{
while(true)
{
std::string text;
std::getline(std::cin, text);
sf::Text tempText(text);
tempText.setColor(sf::Color(102, 23, 123));
tempText.setPosition(0, static_cast<float>(textList.size()*20));
textList.push_back(tempText);
}
}
In my chat I use a font called "french grotesque" (http://www.dafont.com/french-grotesque.font (http://www.dafont.com/french-grotesque.font))
I also tried out other fonts and the default font, but nothing really helped...
Maybe someone knows how to fix this bug, because it's really annoying, espiacially in a chat ;)
Greetings Geheim!
Yes, Laurent does a very good job!
Here is the class, i made it as less as possible!
Chat.h:
#ifndef CHAT_H
#define CHAT_H
#pragma warning(disable : 4355) //warning C4355: this': wird in Initialisierungslisten für Basisklasse verwendet
#include <list>
class Chat
{
private:
sf::RenderWindow &window;
sf::Clock &clock;
sf::Thread writeThread;
std::list<sf::Text> textList;
std::list<sf::Text>::iterator iText;
void writeData();
public:
Chat(sf::RenderWindow &windowGame, sf::Clock &clockGame);
~Chat();
void update();
void render();
};
#endif
Chat.cpp:
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <iostream>
#include <list>
#include "chat.h"
Chat::Chat(sf::RenderWindow &windowGame, sf::Clock &clockGame)
: window(windowGame)
, clock(clockGame)
, writeThread(&Chat::writeData, this)
{
writeThread.launch();
}
Chat::~Chat()
{
//Don't forget to release memory!
textList.clear();
writeThread.terminate();
}
void Chat::update()
{
}
void Chat::render()
{
for(iText=textList.begin(); iText!=textList.end(); ++iText)
window.draw((*iText));
}
void Chat::writeData()
{
while(true)
{
std::string text;
std::getline(std::cin, text);
sf::Text tempText(text);
tempText.setColor(sf::Color(102, 23, 123));
tempText.setPosition(0, static_cast<float>(textList.size()*20));
textList.push_back(tempText);
}
}
Chat::~Chat()
{
//Don't forget to release memory!
textList.clear();
writeThread.terminate();
}
It is not necessary to clear a std::list explicitly if you don't need it anymore. At time of destruction, it automatically releases its memory. So the compiler-generated destructor should be enough.
Furthermore, don't terminate threads. The recommended way is to let them finish execution themselves.
And the list iterator is not part of the object state, so a member variable isn't appropriate. It is only used locally in your render() function, so you can move its declaration there, into the for loop head. Always declare variables as late and as locally as possible :)