Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Qt & SFML  (Read 10395 times)

0 Members and 6 Guests are viewing this topic.

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Qt & SFML
« on: September 15, 2015, 05:56:03 pm »
Hello,

I am now using Qt and a QPushButton is connected to a function that creates an sf::RenderWindow. It appears that the following line is stalled:

GS::window.create(sf::VideoMode(GS::resWidth, GS::resHeight), "Some Window :D");

I was expecting to see a new window pop up (monitored by SFML) when the QPushButton is clicked, but instead the program fizzles. Is there something I should know about using Qt and SFML together?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Qt & SFML
« Reply #1 on: September 15, 2015, 06:50:15 pm »
Quote
the program fizzles
I have no idea what this means :P

Do you have an event loop for your window?
Laurent Gomila - SFML developer

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Qt & SFML
« Reply #2 on: September 15, 2015, 07:04:36 pm »
Quote
the program fizzles
I have no idea what this means :P

Do you have an event loop for your window?
Oh, I only meant that if I print a foo right before, and a foo right after this line, I only get one foo. Yes there's a loop, but my program seems to take infinite time to get past this line, so I never reach the while loop.

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Re: Qt & SFML
« Reply #3 on: September 15, 2015, 07:38:31 pm »
Does the line work in a standalone program without Qt? Maybe there's something incompatible or wrong with your build environment.

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Qt & SFML
« Reply #4 on: September 15, 2015, 07:57:08 pm »
Does the line work in a standalone program without Qt? Maybe there's something incompatible or wrong with your build environment.
Yes, I'm actually merging my SFML project with my Qt project, and the former project was working well before.

Well, even during QApplication::exec, it is possible to create non-Qt windows, right? I mean, nothing in the part of my project that is related to SFML, inherits from QWidget.
« Last Edit: September 15, 2015, 08:33:38 pm by Law »

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Qt & SFML
« Reply #5 on: September 18, 2015, 01:15:11 pm »
So I've actually tried the 1.6 tutorial. I wasn't aware that you couldn't launch an SFML Window out of nowhere when you're already using Qt.

QSFMLCanvas.hpp
#pragma once

#include <QTimer>
#include <QWidget>
#include <SFML/Graphics.hpp>

class QSFMLCanvas : public QWidget, public sf::RenderWindow
{
        private:
       
                QTimer myTimer;
                bool myInitialized;
       
        public:
       
                explicit QSFMLCanvas(QWidget*, const QPoint&, const QSize&, unsigned int = 0);
                QSFMLCanvas(void);
                virtual ~QSFMLCanvas(void);
               
                virtual void showEvent(QShowEvent*);
                virtual QPaintEngine* paintEngine(void) const;
                virtual void paintEvent(QPaintEvent*);
                virtual void OnInit(void);
                virtual void OnUpdate(void);
};

QSFMLCanvas.cpp (not using X11... I mean, if I were using this, I would know right?)
#include <iostream>

#include "QSFMLCanvas.hpp"

QSFMLCanvas::QSFMLCanvas(QWidget* Parent, const QPoint& Position, const QSize& Size, unsigned int FrameTime) :
        QWidget(Parent),
        myInitialized (false)
{
        // Setup some states to allow direct rendering into the widget
        setAttribute(Qt::WA_PaintOnScreen);
        setAttribute(Qt::WA_OpaquePaintEvent);
        setAttribute(Qt::WA_NoSystemBackground);
        // Set strong focus to enable keyboard events to be received
        setFocusPolicy(Qt::StrongFocus);
        // Setup the widget geometry
        move(Position);
        resize(Size);
        // Setup the timer
        myTimer.setInterval(FrameTime);
}

QSFMLCanvas::QSFMLCanvas(void)
{
}

QSFMLCanvas::~QSFMLCanvas(void)
{
}

void QSFMLCanvas::showEvent(QShowEvent*)
{
        if (not myInitialized)
        {
                // Under X11, we need to flush the commands sent to the server to ensure that
                // SFML will get an updated view of the windows
                //XFlush(QX11Info::display());
                // Create the SFML window with the widget handle
                RenderWindow::create(static_cast<sf::WindowHandle>(winId()));
                // Let the derived class do its specific stuff
                OnInit();
                // Setup the timer to trigger a refresh at specified framerate
                connect(&myTimer, SIGNAL(timeout()), this, SLOT(repaint()));
                myTimer.start();
                myInitialized = true;
        }
}

QPaintEngine* QSFMLCanvas::paintEngine(void) const
{
        return 0;
}

void QSFMLCanvas::paintEvent(QPaintEvent*)
{
        // Let the derived class do its specific stuff
        OnUpdate();
        // Display on screen
        RenderWindow::display();
}
void QSFMLCanvas::OnInit(void)
{
}

void QSFMLCanvas::OnUpdate(void)
{
}

MyCanvas.hpp
#pragma once

#include <SFML/Graphics.hpp>
#include "QSFMLCanvas.hpp"

class MyCanvas : public QSFMLCanvas
{
        private:
       
                sf::Clock myClock;
                sf::Texture myImage;
                sf::Sprite mySprite;

        public:
       
                MyCanvas(QWidget*, const QPoint&, const QSize&);
                MyCanvas(void);
                ~MyCanvas(void);
               
                void OnInit(void);
                void OnUpdate(void);
};

MyCanvas.cpp
#include <iostream>
#include <QDir>
#include <string>

#include "MyCanvas.hpp"

MyCanvas::MyCanvas(QWidget* Parent, const QPoint& Position, const QSize& Size) : QSFMLCanvas(Parent, Position, Size)
{
}

MyCanvas::MyCanvas(void)
{
}

MyCanvas::~MyCanvas(void)
{
}

void MyCanvas::OnInit(void)
{
        // Load the image
        std::cout << "onInit" << std::endl;
        QString dir = QDir::currentPath();
        std::string utf8_text = dir.toUtf8().constData();
        std::cout << "HELLO: " << utf8_text << std::endl;
       
        if (not myImage.loadFromFile(utf8_text + "/chef.png"))
                std::cout << "Loading error"<< std::endl;
        else
                std::cout << "Image was loaded fine" << std::endl;
       
        // Setup the sprite
        mySprite.setTexture(myImage);
        mySprite.setPosition(150, 150);
        std::cout << "setting the texture of the sprite" << std::endl;
        //mySprite.setCenter(mySprite.GetSize() / 2.f);
        myClock.restart();
}

void MyCanvas::OnUpdate(void)
{
        // Clear screen
        RenderWindow::clear(sf::Color(0, 128, 0));
        // Rotate the sprite
        mySprite.rotate(myClock.getElapsedTime().asSeconds() * 100.f);
        // Draw it
        RenderWindow::draw(mySprite);
        myClock.restart();
}

The QFrame and MyCanvas instances are defined as public static std::shared_ptr of some class:
class WindowFrame : public QObject
{
        Q_OBJECT

                // ...
       
        public:
       
                static std::shared_ptr<QFrame>                          SFMLFrame;
                static std::shared_ptr<MyCanvas>                        SFMLWindow;
               
                WindowFrame(void);
                ~WindowFrame(void);

                // ...
};

Now, here's what my main function looks like:
int main(int argc, char *argv[])
{
        QApplication app(argc, argv);

        WindowFrame::SFMLFrame = std::make_shared<QFrame>();
        WindowFrame::SFMLFrame->setWindowTitle("Qt SFML");
        WindowFrame::SFMLFrame->resize(GS::resWidth, GS::resHeight);
        WindowFrame::SFMLFrame->show();
       
        WindowFrame::SFMLWindow = std::make_shared<MyCanvas>(WindowFrame::SFMLFrame.get(), QPoint(0, 0), QSize(GS::resWidth, GS::resHeight));
        WindowFrame::SFMLFrame->show();
       
        // stuff irrelevant to SFML
        return app.exec();
}

But I still have the same problem as before... The following line is stalled indefinitely, when I press a QPushButton that causes its execution:
WindowFrame::SFMLWindow->sf::RenderWindow::create(sf::VideoMode(GS::resWidth, GS::resHeight), "Some Window :D");

So, what am I doing wrong in all this? Is there nothing too redundant in doing:
WindowFrame::SFMLFrame->resize(GS::resWidth, GS::resHeight);
// ...
WindowFrame::SFMLWindow = std::make_shared<MyCanvas>(WindowFrame::SFMLFrame.get(), QPoint(0, 0), QSize(GS::resWidth, GS::resHeight));

Thank you in advance.
« Last Edit: September 25, 2015, 06:34:36 pm by Law »

AlexxanderX

  • Full Member
  • ***
  • Posts: 128
    • View Profile
    • AlexanderX
Re: Qt & SFML
« Reply #6 on: September 18, 2015, 01:25:24 pm »
I don't know if I understood the problem but it would not be easier to put the sfml window( the loop) in a separated thread and then call it.
Here you can find my blog and tutorials about SFML - http://alexanderx.net/ (died...) - http://web.archive.org/web/20160110002847/http://alexanderx.net/

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Qt & SFML
« Reply #7 on: September 18, 2015, 01:58:15 pm »
You mean would right? Anyway I hear that using std::threads is very nasty for these things, so I'd rather avoid them for now.

I would really, really appreciate if someone could take the time to help me out here. I don't want to be a pain and bump this thread every day or so.

Addendum: I've just realized that the code in my main function has a mistake. It should be
    WindowFrame::SFMLWindow = std::make_shared<MyCanvas>(WindowFrame::SFMLFrame.get(), QPoint(0, 0), QSize(GS::resWidth, GS::resHeight));
    WindowFrame::SFMLWindow->show();

not
    WindowFrame::SFMLWindow = std::make_shared<MyCanvas>(WindowFrame::SFMLFrame.get(), QPoint(0, 0), QSize(GS::resWidth, GS::resHeight));
    WindowFrame::SFMLFrame->show();

Once I corrected that, my program stalls at
    WindowFrame::SFMLWindow->show();

and doesn't even reach `app.exec()`
« Last Edit: September 18, 2015, 08:31:41 pm by Law »

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Qt & SFML
« Reply #8 on: September 18, 2015, 08:27:31 pm »
So I've actually tried the 1.6 tutorial. I wasn't aware that you couldn't launch an SFML Window out of nowhere when you're already using Qt.
Think about "who's managing the event loop"?...

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Qt & SFML
« Reply #9 on: September 21, 2015, 04:32:24 pm »
Anyone know why calling QWidget::show() stalls the program? Also, how can I put my SFMLCanvas instance (SFMLWindow) in VideoMode without actually calling sf::RenderWindow::create(), which seems to stall the program as well ?
« Last Edit: September 21, 2015, 04:33:59 pm by Law »

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Qt & SFML
« Reply #10 on: September 25, 2015, 06:35:13 pm »
Help please. I can't seem to use show() without the entire program blocking. I've also injected

std::cout << "foo" << std::endl;

to see if any of the following functions

virtual void showEvent(QShowEvent*);
virtual QPaintEngine* paintEngine(void) const;
virtual void paintEvent(QPaintEvent*);

from QSFMLCanvas were called, it seems they aren't for whatever reason. The same trick shows that the following functions

void OnInit(void);
void OnUpdate(void);

from MyCanvas are never called either.

I'm starting to wonder if I posted my problem in the correct section. Window might have been more accurate. Or maybe General.
« Last Edit: September 26, 2015, 01:07:06 am by Law »

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Qt & SFML
« Reply #11 on: September 27, 2015, 07:18:58 pm »
Well I understand that reading through the code isn't really interesting, so everybody's busy doing something else. But if I can't even get hints or methods on how to solve the problem myself, I really don't know where to go. I'm pretty sure the problem is basic though, as I've rarely had complicated problems in coding so far.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Qt & SFML
« Reply #12 on: September 27, 2015, 10:17:53 pm »
First, what do you want to do? The canvas is parented to the frame, but isn't inserted in it (with a layout for example). Or do you want two independant top-level windows?

Then you could simply use your debugger to find out where your program is blocked exactly (in which Qt call).
Laurent Gomila - SFML developer

Law

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Qt & SFML
« Reply #13 on: September 28, 2015, 01:46:46 pm »
First, what do you want to do? The canvas is parented to the frame, but isn't inserted in it (with a layout for example). Or do you want two independant top-level windows?

Then you could simply use your debugger to find out where your program is blocked exactly (in which Qt call).
Thanks for your reply.

I don't understand, is there any need for Layouts? Either it's an oversight, or the tutorial I used didn't use any. I just gave the pointer of the Frame as the first parameter of the MyCanvas constructor:

WindowFrame::SFMLWindow = std::make_shared<MyCanvas>(WindowFrame::SFMLFrame.get(), QPoint(0, 0), QSize(GS::resWidth, GS::resHeight));

I've never managed to use the debugger under Ubuntu, so I'd rather try out any other ways to solve this issue first :S

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Qt & SFML
« Reply #14 on: September 28, 2015, 02:00:23 pm »
Before trying to integrate SFML into a Qt GUI, did you first learn Qt alone? Have you already successfully created a GUI without SFML?
Laurent Gomila - SFML developer