1
votes

I've been trying to learn Qt for the purposes of embedding a GUI on top of my OpenGL projects. In this case, the idea is to have my OpenGL viewport fill my main window. I have a simple QtWidget-based GUI that contains a 'RenderSurface' which is a subclass of QGLWidget. However, I've noticed that making my RenderSurface a child of my MainWindow has unwanted effects on my GUI's layout.


Here's the simple MainWindow code and screen shot without use of parenting:

#include "mainwindow.h"
#include "rendersurface.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    renderSurface()
{
    setCentralWidget(&renderSurface);

    setWindowTitle("QtGL Test");
}

MainWindow::~MainWindow()
{
}

RenderSurface is NOT a child of MainWindow.

In this case, my RenderSurface (QGLWidget subclass) is not passed a pointer to any parent QWidget when I call its constructor in the MainWindow initialization list. You can see that the dark grey OpenGL context fits the size of the window, and it seems to fill the window even when I expand and contract the window size.

Here's the same thing with parenting:

#include "mainwindow.h"
#include "rendersurface.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    renderSurface(this)
{
    setCentralWidget(&renderSurface);

    setWindowTitle("QtGL Test");
}

MainWindow::~MainWindow()
{
}

enter image description here

Simply passing 'this' to the RenderSurface constructor instead changes the way that my OpenGL context is initially rendered in my window. It's also worth noting that my RenderSurface will start filling my window properly once I resize the window by dragging an edge.


Why does making my RenderSurface a child of my MainWindow cause this issue? How can I avoid this buggy-looking behaviour? Also, since my GUI seems to work better without parenting, what are some pros and cons of object parenting in Qt?

2

2 Answers

4
votes
  • Case 1 : You are effectively using QMainWindow layout, which is a specific layout implementation to the same extent as QGridLayout or QStackedLayout.
  • Case 2 : You are using the default Qt widget layout, which have a more loose setup of the children widgets. The only condition I know of is that children rectangles are within the parent rectangle and their default position is 0,0. The layout will not resize the children.

setCentralWidget(&renderSurface);will try to add renderSurface to the Qmainwindow layout. In case 2, rendersurface is already inside a layout, so this attempt will fail.

Also, since my GUI seems to work better without parenting

You are incorrect about the parenting part. In both case renderSurface becomes a child of the window.

QWidget* w = new Qwidget(0);
QLayout* l = new QHBoxLayout();

l->add(w);
setLayout(l);

During setLayout all widgets in the layout will have their affinity changed to the widget owning the layout. w is no more a parentless widget.

When a widget is going to be added to a layout, the best thing is to create it without a parent like you did. The correct parent is going to be set later.

1
votes

It is a known issue. I like this answer as well: A widget with a parent doesn't become a window but is embedded into its parent. If you don't put it in a layout it might end up in a strange place on the parent and might have an arbitrary size (0x0 included). So if you want your widget to be a window, simply don't pass a parent at all. So the layout you put the widget in is the key for rendering in this case and QMainWindow is not a layout but can have a layout or a few on its own.

On the other hand, setCentralWidget is already taking care of releasing the embedded widget so there is no reason to provide the parent pointer for such widget. And setCentralWidget makes an unparented widget central and correctly drawable as if in layout.