Search code examples
c++qt5qmainwindowqgraphicswidget

Is it possible to use QGraphicsLayout in an application with a QMainWindow?


What I was hoping to do was have a standard QMainWindow class with menus, toolbar, plus various widgets in a layout, one of which would be a graphics view showing a graphics widget that contained a graphics layout. But whenever I put the graphics view into a main window nothing gets displayed. If I create my graphics view with the graphics widget containing a layout inside the main() function, then everything is visible.

As a test I took the working code provided in the Qt Basic Graphics Layouts Example, created a QMainWindow class in main, and moved the QGraphicsScene, Window and QGraphicsView creation to the main window class.

I tested the main window class on its own, and widgets like a line edit show up fine. But the code below, taken from main in the example, no longer works when in the main window class.

QGraphicsScene scene;

Window *window = new Window;
scene.addItem(window);
QGraphicsView view(&scene);
view.resize(600, 600);
view.show();

I just get a blank area. If I don't add the Window widget, but instead, for example, draw an ellipse then that is visible. If I add a plain QGraphicsWidget with a background colour then that is also visible. It is just when things are inside a layout on a graphics widget that I get nothing. I've been searching for answers, digging into the documentation and even looking through the Qt source to see if I can figure out if what I am trying to do is even possible, but without any luck.

My main window:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QGraphicsScene scene;

    Window *window = new Window;
    window->resize(600, 600);
    scene.addItem(window);
    QGraphicsView view(&scene);
    view.resize(600, 600);
    view.show();

    setCentralWidget(&view);
    resize(600,600);
}

Code in main:

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

    MainWindow w;
    w.show();

    return app.exec();
}

Solution

  • One problem is here:

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
       [...]
    
       QGraphicsView view(&scene);
       view.resize(600, 600);
       view.show();
    
       [...]
    }
    

    You've declared the view widget on the stack, which means it will be automatically destroyed as soon as your MainWindow constructor returns, and thus the user will never see it. What you should do instead is something like this:

    QGraphicsView * view = new QGraphicsView(&scene, this);
    view->resize(600, 600);
    view->show();
    

    You'll have a similar problem with your QGraphicsScene object:

    QGraphicsScene scene;
    

    ... since it is also declared as a local variable inside the constructor-method, it will also be destroyed when the constructor-method returns, leaving you with no scene. I suggest making it a class-member variable instead; that way it will last as long as your MainWindow does.

    (Note that declaring items on the stack worked in the example-program you copied from, only because they were declared in the directly in the main() method, and main() doesn't return until the program is ready to exit... thus the objects in the example program would not be destroyed until the program was exiting anyway)