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

Author Topic: Screen Artifacts with QSFMLWidget and QDockWidget  (Read 3084 times)

0 Members and 1 Guest are viewing this topic.

dvstate

  • Newbie
  • *
  • Posts: 4
    • View Profile
Screen Artifacts with QSFMLWidget and QDockWidget
« on: October 16, 2016, 08:01:25 am »
Hoping someone has a quick and simple answer for this. It's been driving me crazy for a few days now.

I have the QSFMLWidget class (publicly available) to display an SFML RenderWindow as a QtWidget. In a simple Qt app, for example with the QSFMLWidget as the central widget of the MainWindow, everything works perfectly.

Now I need to render multiple 2D scenes within QDockWidgets. Adding the QSFMLWidget to a QDockWidget seems to work fine UNTIL the QDockWidget is dragged outside of the main window. When the QDockWidget is dragged back inside the MainWindow and redocked, artifacts are left on the screen the size of the RenderWindow.

I am NOT yet attempting to render multiple scenes, or even use more than 1 QDockWidget. I can put another type of widget into the QDockWidget and it works just fine.

I am using CentOS 7, XFCE, QT 5.5, SFML 2.3.2.

Thank you,
David

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Screen Artifacts with QSFMLWidget and QDockWidget
« Reply #1 on: October 16, 2016, 09:03:51 am »
Quote
When the QDockWidget is dragged back inside the MainWindow and redocked, artifacts are left on the screen the size of the RenderWindow
I think it could help to see those artifacts, or at least have a better description of them ;)
Laurent Gomila - SFML developer

dvstate

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Screen Artifacts with QSFMLWidget and QDockWidget
« Reply #2 on: October 17, 2016, 04:08:58 am »
 :) Was hoping someone had experience with the issue and knew what stupid mistake I was making.

Thank you for your prompt response, and also for making such a great 2D library. I've used it quite a bit over the years, and this is the first issue that's stumped me.

I'm running XFCE on CentOS 7 via Vagrant using Parallels. When I drag the DockWidget out of the MainWindow, it floats properly on its own, but when I re-dock it within the MainWindow, a visual artifact remains on the screen. Screenshot below. Also, posted below is complete and minimal code that should, hopefully, replicate the issue.

Thank you,
David



QSFMLCanvas.h
#ifndef _QSFMLCANVAS_H_
#define _QSFMLCANVAS_H_

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

class QSFMLCanvas : public QWidget, public sf::RenderWindow
{
public :

    QSFMLCanvas(QWidget* Parent, const QPoint& Position, const QSize& Size, unsigned int FrameTime = 0);

    virtual ~QSFMLCanvas();

private :

    virtual void on_init();

    virtual void on_update();

    virtual QPaintEngine* paintEngine() const;

    virtual void showEvent(QShowEvent*);

    virtual void paintEvent(QPaintEvent*);

    QTimer m_timer;
    bool   m_initialized;
};

#endif
 

QSFMLCanvas.cpp
#include "QSFMLCanvas.h"

QSFMLCanvas::QSFMLCanvas(QWidget* Parent, const QPoint& Position, const QSize& Size, unsigned int FrameTime)
    : QWidget(Parent), m_initialized(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
    m_timer.setInterval(FrameTime);
}

QSFMLCanvas::~QSFMLCanvas()
{

}

#ifdef Q_WS_X11
    #include <Qt/qx11info_x11.h>
    #include <X11/Xlib.h>
#endif

void QSFMLCanvas::showEvent(QShowEvent*)
{          
    if (!m_initialized)
    {
        #ifdef Q_WS_X11
            XFlush(QX11Info::display());
        #endif
         
        // Create the SFML window with the widget handle
        RenderWindow::create((sf::WindowHandle)(winId()));
       
        // Let the derived class do its specific stuff
        // NOTE: Inside on_init, the RenderWindow View should be assigned!
        on_init();
       
        // Setup the timer to trigger a refresh at specified framerate
        connect(&m_timer, SIGNAL(timeout()), this, SLOT(repaint()));
        m_timer.start();
       
        m_initialized = true;
    }
}

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

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

void QSFMLCanvas::on_init() {}
void QSFMLCanvas::on_update() {}
 

MyWindow.h
#ifndef _MYWINDOW_H_
#define _MYWINDOW_H_

#include "QSFMLCanvas.h"
#include <QMainWindow>

class MyWindow : public QMainWindow
{
    Q_OBJECT

public:
    MyWindow();
    virtual ~MyWindow();

private:
   QSFMLCanvas* canvas;
};

#endif // _MYWINDOW_H_
 

MyWindow.cpp
#include "MyWindow.h"
#include <QtWidgets>

MyWindow::MyWindow()
{
    QDockWidget *dock = new QDockWidget(tr("Scene"), this);
    dock->setAllowedAreas(Qt::AllDockWidgetAreas);
   
    canvas = new QSFMLCanvas(this, QPoint(0, 0), QSize(100, 100), 100/*10Hz*/);
    canvas->show();
   
    dock->setWidget(canvas);
   
    addDockWidget(Qt::RightDockWidgetArea, dock);
}

MyWindow::~MyWindow()
{}


#include "MyWindow.moc"
 

main.cpp
#include <QApplication>
#include "MyWindow.h"

int main(int argc, char** argv)
{  
    QApplication app(argc, argv);
    MyWindow w;
    w.setMinimumSize(800,600);
    w.show();
    return app.exec();
}
 

Yohdu

  • Newbie
  • *
  • Posts: 26
    • View Profile
    • Email
Re: Screen Artifacts with QSFMLWidget and QDockWidget
« Reply #3 on: October 17, 2016, 09:05:20 am »
Hello!

I cannot try your code at the moment, but I myself had (and still have !) some issues integrating properly SFML with Qt. Did you try handling resize events:
  • from the sf::RenderWindow perspective (and reset the sf::View with the proper width/height)?
  • from the QtWidget perspective (and force a repaint at this moment)?
Not sure it will help, I'll try your code when I have time :)
« Last Edit: October 17, 2016, 09:10:17 am by Yohdu »

dvstate

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Screen Artifacts with QSFMLWidget and QDockWidget
« Reply #4 on: October 17, 2016, 04:31:14 pm »
The code I posted above is stripped down to help others replicate the issue. In my actual project, I'm handling the resize event of the widget and updating the view as well as the GL viewport and projection matrix since I'm using native OpenGL calls as well. The rendering and functionality of my 2D scene are fine. The only issues occur when it's used on a QDockWidget that is moved around.

The QDockWidget behaves fine with any other type of widget. The weirdness only happens when the sf::RenderWindow is used on the QDockWidget.

dvstate

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Screen Artifacts with QSFMLWidget and QDockWidget
« Reply #5 on: October 17, 2016, 07:05:53 pm »
I just ran tests on Mac OSX, to rule out CentOS/Parallels/XFCE, and I observe similar issues with SFML and QDockWidget.

Under Mac OSX, the QDockWidget example projects provided by Qt run fine. But when I try to add an SFML RenderWindow to a widget, docking no longer works properly. The artifacts don't appear on the screen as in CentOS, but the QDockWidget cannot be re-docked to the main window.

After creating a sf::RenderWindow and calling it's create() function, Qt docking behavior is all jacked up. Now verified under Mac OSX and CentOS.

Would love to see someone provide a working QDockWidget example with SFML.

Thanks,
David

korczurekk

  • Full Member
  • ***
  • Posts: 150
    • View Profile
    • Email
Re: Screen Artifacts with QSFMLWidget and QDockWidget
« Reply #6 on: October 17, 2016, 08:20:43 pm »
@Up
Have you tried closing sf::RenderWindow when QDockWidget is being moved and then opening it again? I may take a look later and try to fix it in QSFML.

 

anything