SFML community forums

Help => General => Topic started by: Foaly on May 30, 2012, 05:52:19 pm

Title: SFML and Qt
Post by: Foaly on May 30, 2012, 05:52:19 pm
Hello everybody,
I would like to use SFML and Qt together, but not in the way that is described in the tutorials (I don't want to integrate a SFML view in a Qt interface). I would like to have two separate windows, one Qt window with a couple controls and one SFML window, that renders stuff.
I am not sure what the best way of doing this is. Could someone point me in the right direction? Should I use two different threads?
Thanks in advance,
Foaly
Title: Re: SFML and Qt
Post by: Laurent on May 30, 2012, 05:59:59 pm
Yes, I think that two different threads will be the simplest solution.

Another approach would be to have a global QTimer in the main thread, that ticks at a regular interval (such as 60 fps), and handle all your SFML stuff (events and drawing) there.
Title: Re: SFML and Qt
Post by: Foaly on June 04, 2012, 07:04:34 pm
I tried using threads and it worked very well. But I have a little question regarding a mutex. I want the sf::RenderWindow to close when the QT Window closes (or when a button is clicked). This is how I do it:
I created a class that has a Run function, which looks like this:
void CRenderThread::Run()
{
    sf::RenderWindow RenderWindow(sf::VideoMode(300, 200), "SFML works!");
    sf::Text text("SFML works");
    m_bRunning = true;

    while (RenderWindow.isOpen() && m_bRunning)
    {
        sf::Event event;
        while (RenderWindow.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                RenderWindow.close();
        }

        RenderWindow.clear();
        RenderWindow.draw(text);
        RenderWindow.display();
    }

    RenderWindow.close();

    return;
}
 
The class also has a Exit function which looks like this:
void CRenderThread::Exit()
{
    m_bRunning = false;
}
 
The Run function is the thread function, which I create in main(). The Thread is a public member of my (Qt) QMainwindow. So it looks a bit complicated:
    QMainWindow w;

    sf::Thread thread(&CRenderThread::Run, &w.RenderThread);
    thread.launch();
The reason the Thread is a member of my QMainWindow is, so that I can call the exit function from there (on button click or on close). But my Question is: I obviously need a mutex to secure my m_bRunning from being assigned to false in the wrong moment. But where do I have to put the Lock? Obviously around the false assigment in the exit function, but I cant put the other before the while (RenderWindow.isOpen() && m_bRunning), because the lock would never open until the while loop finishes. And inside the while loop wouldn't make to much sense either, because the m_nRunning lookup already happened.
I don't really know what to do. I hope this is not a stupid question and that I'm not simply missing something. Thanks in advance,
Foaly
Title: Re: SFML and Qt
Post by: Laurent on June 04, 2012, 07:23:27 pm
A clean solution is to encapsulate it in a (private) function:
bool CRenderThread::IsRunning() const
{
    sf::Lock lock(m_mutex);
    return m_bRunning;
}

void CRenderThread::Run()
{
    ...

    while (RenderWindow.isOpen() && IsRunning())
    {
        ...

Note that your mutex must be declared as mutable so that it can be locked in a const member function.

If you work with compilers that support the new C++11 standard library, you can also use an atomic int (more efficient and simpler to write).
Title: Re: SFML and Qt
Post by: Foaly on June 04, 2012, 07:40:24 pm
Wow! Thanks for the super fast reply! I tried it and it worked perfectly!
One question though: Why do I have to declare the member function as const? And what does the keyword mutable do?

I'll have a look into atomic int (but for now I'll stay with the sf::Mutex :) )

edit: Just wondering: why do you call sf::Lock lock(&m_mutex);? I always do sf::Lock lock(m_mutex);? Is that wrong? I think i read it like that in the doc...
Title: Re: SFML and Qt
Post by: Laurent on June 04, 2012, 08:59:12 pm
Quote
Why do I have to declare the member function as const?
You don't have to, but if this kind of function is not const then I wonder which function is ;)
It's a good habit to always have const-correctness in mind when you write new code.

Quote
And what does the keyword mutable do?
It allows the member to be modified in a const function, which is normally disallowed. It's useful for members that are not part of the "public state" of the object, but are only internal details.

Quote
Just wondering: why do you call sf::Lock lock(&m_mutex);?
My code was wrong, sorry. I'm too used to other libraries (Qt).
Title: Re: SFML and Qt
Post by: Foaly on June 04, 2012, 11:06:32 pm
I don't really get why declaring member functions as const is an advantage. I couldn't find anything that tells me why.
But again, thanks for the excellent and quick reply!
Title: Re: SFML and Qt
Post by: Laurent on June 04, 2012, 11:16:21 pm
Quote
I don't really get why declaring member functions as const is an advantage. I couldn't find anything that tells me why.
It would be too long to explain on a forum, but I'm sure you can find good articles about the importance of const-correctness in C++.
Take the time to understand that, it's very important.
Title: Re: SFML and Qt
Post by: Foaly on June 05, 2012, 08:23:46 pm
OK I'll have another look into that :)

Another question (well it's almost the same... :D) : In my thread I draw everything to a RenderTexture. Then of course I use a Sprite to display the RenderTexture in my window. Code looks like this:
        mySprite.setTexture(myRenderTExure.getTexture());

        window.clear();
        window.draw(mySprite);
        window.display();
Now I need to change the opacity of that RenderTexture (changing the sprites color), but my question is how do I do this Thread safe? I was gonna use a function, which the gui elements can call, which contains a lock. But how do i make the window display, draw, clear safe? I can't really put that in a function...
Title: Re: SFML and Qt
Post by: Laurent on June 05, 2012, 08:47:06 pm
If you're only going to change mySprite's color, then only calls involving mySprite need to be protected by a mutex. You can even use an extra member variable to store the color, and assign it to your sprite in the rendering thread so that you only have one variable to protect, at only two places, and you don't need to lock potentially long calls.
Title: Re: SFML and Qt
Post by: Foaly on June 05, 2012, 11:28:11 pm
If you're only going to change mySprite's color, then only calls involving mySprite need to be protected by a mutex.
Yes I know that, but the window.draw(mySprite); call involves mySprite my question was how do I protect that without a having to put a Lock into the whole render part of the while loop. Should I put it into a function too?
Title: Re: SFML and Qt
Post by: Laurent on June 06, 2012, 08:19:32 am
mutex.lock();
window.draw(mySprite);
mutex.unlock();
Title: Re: SFML and Qt
Post by: Foaly on June 06, 2012, 08:37:15 am
Ok Thanks. But that means that the code won't be exception safe right?
Title: Re: SFML and Qt
Post by: Laurent on June 06, 2012, 09:03:35 am
Yes. But SFML functions don't throw exceptions ;)
Title: Re: SFML and Qt
Post by: Foaly on June 06, 2012, 09:05:23 am
Well that question was stupid then haha thank you very much though!
Title: Re: SFML and Qt
Post by: Laurent on June 06, 2012, 09:10:18 am
It was not stupid, it's also a good strategy to assume that everything may throw, and make all your code exception-safe. In this case you can do this:
window.clear();
{
    sf::Lock lock(m_mutex);
    window.draw(sprite);
}
window.display();
Title: Re: SFML and Qt
Post by: Foaly on June 06, 2012, 09:14:15 am
Ah ok. That is a good idea. I'll try that later. Thanks again for all the help.