qtopenglqt5qglwidget

Implementing QGLWidget as viewport on Qt 5.12


I have a fully working application that makes use of QGraphicsView + QGLWidget and QGraphicsScene to draw a 3D scene with user interaction. The concept is explained in the Boxes example from Qt5.

Since updating to Qt 5.12 the application doesn't work anymore. Apart from some other minor issue that I already fixed, now I have everything setup, but the viewport doesn't display anything.

I created a minimum concept program that creates a QGraphicsView, a QGLWidget as a viewport, and a QGraphicsScene derived class that draws the viewport.

I setup everything, but the QGraphicsScene::DrawBackground() function isn't called.

The interesting part is that the application works fine in Qt 5.6 but doesn't in 5.12.

What has changed between the two versions?

Following is the sample app:

CMakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(Prototypes)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -Wall)

find_package(Qt5 REQUIRED COMPONENTS Core Widgets OpenGL)

add_executable(Prototypes main.cpp GraphicsView.cpp GraphicsView.h Scene.cpp Scene.h)

target_link_libraries(Prototypes Qt5::Core Qt5::OpenGL Qt5::Widgets)

main.cpp

#include "GraphicsView.h"
#include "Scene.h"

#include <QApplication>
#include <QGLWidget>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers));
    widget->makeCurrent();

    Scene scene(1024,768);

    GraphicsView view;
    view.setViewport(widget);
    view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    view.setScene(&scene);

    view.resize(800, 600);
    view.show();

    return app.exec();
}

Scene.h

#ifndef PROTOTYPES_SCENE_H
#define PROTOTYPES_SCENE_H

#include <QGraphicsScene>

class QTimer;

class Scene : public QGraphicsScene {
    Q_OBJECT
public:
    Scene(int width, int height);
protected:

    QTimer *m_timer;
    void drawBackground(QPainter *painter, const QRectF &rect) override;

};


#endif //PROTOTYPES_SCENE_H

Scene.cpp

#include "Scene.h"

#include <QPainter>
#include <QDebug>
#include <QTimer>

Scene::Scene(int width, int height)
{
    setSceneRect(0,0,width, height);

    //m_timer = new QTimer(this);
    //m_timer->setInterval(20);
    //connect(m_timer, SIGNAL(timeout()), this, SLOT(update()));
    //m_timer->start();
}

void Scene::drawBackground(QPainter *painter, const QRectF &rect)
{
    qDebug() << "DrawBackground";    
}

GraphicsView.h

#ifndef PROTOTYPES_GRAPHICSVIEW_H
#define PROTOTYPES_GRAPHICSVIEW_H

#include <QGraphicsView>

class GraphicsView : public QGraphicsView {
public:
    GraphicsView();
protected:
    void resizeEvent(QResizeEvent *event) override;

};


#endif //PROTOTYPES_GRAPHICSVIEW_H

GraphicsView.cpp

#include "GraphicsView.h"

#include <QResizeEvent>
#include <QDebug>

void GraphicsView::resizeEvent(QResizeEvent *event)
{
    if (scene()) {
        qDebug() << "Set Scene Rect " << event->size();
        scene()->setSceneRect(QRect(QPoint(0, 0), event->size()));
    }
    QGraphicsView::resizeEvent(event);
}

GraphicsView::GraphicsView()
{
    setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
}

Solution

  • As per the comment, QGLWidget has been marked obsolete for some time and comes with the warning...

    This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code.

    The solution is to use QOpenGLWidget instead.