Question

What I am basically trying to do is to create one instance of a QGLWidget (or rather a derived class of QGLWidget), add it to a QMainWindow, and then access the QGLWidget's rendering context from anywhere in my QTCreator program to be able to call naked OpenGL anywhere I chose to.

Things I have tried:

1) Creating a subclass of QGLWidget called OGLWidget and making that into a singleton, and then trying to subclass the singleton class "OGLWidget". I thought this would give me access to the same rendering context that the OGLWidget singleton was using but it didn't work.

2) using the constructor QGLWidget(QWidget * parent, QGLWidget * shared, Qt::WindowFlags). For this one I tried casting the singleton object to a QGLWidget and then sticking it in this constructor when I was subclassing QGLWidget in another class called "Display". I tried calling makeCurrent before each classes openGl calls but only the original singleton would draw. I also checked isSharing and that returned true.

Was it helpful?

Solution

First of all, although signals\slots are a powerful and awesome feature of Qt I would never use them in my rendering routines because of the added overhead and render order problems; especially the latter. Besides, it's not necessary to do it the way you propose. Thus, your idea of scattering the rendering routines all over your project is a very bad idea in my opinion. What I do in my own project is the following:

My derived QGLWidget owns a Renderer class that's implemented as a Singleton. It contains all of the OpenGl calls in a few functions. I've created a system where everything that's drawable derives from the same base class. When I want to render, I build a render queue which I implemented as a priority_queue with custom sort function. When It's time for rendering a frame I just keep poppin' and rendering until the queue is empty. Doing this with an event driven render system, while maintaining correct render order would probably drive you insane.

For completeness, my (simplified) QGLWidget definition:

#include <QtOpenGL/QGLWidget>

#include "global.h"
#include "renderer.h"

/**
 * Derivation of QGLWidget.
 */
class Engine : public QGLWidget
{
    Q_OBJECT
private:
    Renderer* renderer;
private slots:
    void renderTimeout(); // my render-loop is timer based
    void onTap(QMouseEvent* qme);
    void onMove(QMouseEvent* qme);
protected:
    void initializeGL();
    void resizeGL(int w, int h);
    /* for debugging I use QPainter for drawing overlays, 
     * so I can't use PaintGL */
    void paintEvent(QPaintEvent *event); 
    void mousePressEvent(QMouseEvent* qme);
    void mouseMoveEvent(QMouseEvent* qme);
public:
    Engine( QWidget* parent = 0 );
    ~Engine();
signals:
    void tapOccurred(QMouseEvent* qme);
    void moveOccurred(QMouseEvent* qme);
};

OTHER TIPS

Why don't you just use what Qt has been designed for: use signals and slots? Maybe your problem is more complicated than what I get from it at first glance, but it seems to me that if you add slots to your QGLWidget and connect them to signals anywhere in your application, you accomplish exactly what you want. Connecting them can for example be done in the QMainWindow. This slot can then make a call to an implementation of paintGL() or paintEvent() to update the area in QGLWidget. Like this:

class MyQGLWidget : public QGLWidget {
// constructors and destructor...

protected:
    void paintGL();      // <-- implement this in any way you want if you use OpenGL
    void paintEvent();   // <-- or implement this one if you prefer using QPainter

public slots:
    void updateMyWindow();
}

void MyQGLWidget::updateMyWindow() {
    // Change some data here in any way you like
    // ...

    paintGL();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top