Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QMainWindow's content turns black after QMdiSubWindow closes

QMainWindow's content turns black after QMdiSubWindow closes

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 2 Posters 5.4k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    CamelFrog
    wrote on last edited by
    #1

    Hi,

    I have a display glitch in my GUI when I close subwindows in an MDI area.
    My GUI is made with Qt Creator. Qt 5.7.1, Qt Creator 4.2.0. This issue never occurs on mac, but it occurs on every windows pc tested so far, either NVIDIA or Intel graphics.

    Here are more details:

    My MainWindows header starts like this:

    namespace Ui {
    class RMainWindow;
    }
    
    class RMainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit RMainWindow(QWidget *parent = 0);
        ~RMainWindow();
    

    And the .cpp

    using namespace std;
    
    RMainWindow::RMainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::RMainWindow),
        currentROpenGLWidget(NULL)
    {
        ui->setupUi(this);
        this->showMaximized();
        setCentralWidget(ui->mdiArea);
    

    So right here I setup my QMdiArea that comes from the ui.

    '''currentROpenGLWidget''' is an object that inherits a QOpenGLWidget. I indeed display images in there as textures using my own shaders. This QOpenGLWidget is set in a QScrollArea (so I can scroll through large textures horizontally and vertically). And the latter is set in a QMdiSubwindow, as follows:

    void RMainWindow::loadSubWindow(QScrollArea *scrollArea)
    {
        currentSubWindow = new QMdiSubWindow;
        currentSubWindow->setWidget(scrollArea);
        ui->mdiArea->addSubWindow(currentSubWindow);
        currentSubWindow->setAttribute(Qt::WA_DeleteOnClose, true);
    }
    

    The purpose of this method is to open a new subwindow when I drag an image file into the QMdiArea. The subwindow displays, and I can scroll through the image (see screenshot1 and screenshot 2).
    I can load more windows without issues.
    The problems occur when I close one of the subwindows. The content of the RMainWindow's, including the docks, turns black, some elements of the GUI sometimes remain visible, but that's a bit random, most of the time it's all black. Then if I hover the move on either dock (right-hand side or bottom), then the buttons show up again but the glitch persists everywhere else: see screenshot 3 and screenshot 4
    Sometimes if I click on the button that takes the window out of full screen mode, everything somewhat refresh and would show up normally again, only sometimes.

    Of course, there are more codes than what I show, for resizing the different windows when they first show up, to the size I prefer, but I prefer to limit copy pasting code 'cause maybe you'll already see a problem here. If not, I can show more.

    Do you think the QMdiArea needs some explicit refresh or update() after closing a window? If yes, what would be the cleanest way to do it? Through a connect maybe?

    Thanks for the help

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      There might be something going in with your OpenGL widget. Can you check whether it's still the case with Qt 5.8 ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      C 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi,

        There might be something going in with your OpenGL widget. Can you check whether it's still the case with Qt 5.8 ?

        C Offline
        C Offline
        CamelFrog
        wrote on last edited by
        #3

        @SGaist Hmm... ok, i've been hoping it would not be the QOpenGLWidget, so far it's been my weak spot. I'll update and give it a try. What makes you think Qt 5.8 can solve this? What changed in the QOpenGLWidget class that could relate to this? Any theory on why it's working on mac without issue?

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          In case of a bug, it's always a good idea to check with the current stable release.

          Well, not the same platform, not the same backend, not the same hardware, not the same drivers.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          C 1 Reply Last reply
          0
          • SGaistS SGaist

            In case of a bug, it's always a good idea to check with the current stable release.

            Well, not the same platform, not the same backend, not the same hardware, not the same drivers.

            C Offline
            C Offline
            CamelFrog
            wrote on last edited by CamelFrog
            #5

            @SGaist ok. I made a last test, still under Qt 5.7: taking the code above (loadSubWindow()), simply removing

                currentSubWindow->setAttribute(Qt::WA_DeleteOnClose, true);
            

            [EDIT] fixes the issue.

            Yet when I keep that line above, but not setting either the QOpenGLWidget in the QScrollQrea, or not setting the QScrollArea in the SubWindow, then there is no glitch when closing the subwindow.
            Does that make any sense? That seems to support the implication of the QOpenGLWindow..

            Can't really remember what made me use the WA_DeleteOnClose... I'm not using a derived class, it's the very QMdiSubWindow class. In your opinion, which is cleaner in this context? Set as true or false? I was afraid of some memory leak so I was inclined to set it to true. I am indeed opening and closing those all the time... They are series of images that can be of a few GB, and loaded as textures in the GPU; and it was unclear when Qt actually destroys theses objects and the widgets set in the QMdiSubWindows.

            Let's update to Qt 5.8 anyway and see...

            [EDIT] Forgot to write above, simply romeving that line above is enough to fix the problem, with my QOpenGLWidget set in there.

            1 Reply Last reply
            0
            • C Offline
              C Offline
              CamelFrog
              wrote on last edited by
              #6

              I just updated to Qt 5.8. My app won't even start. Crashes immediately, doesn't even load the ui. In debug mode i have the "CDB process terminated". Yet it compiles without issue.

              My .pro file was unchanged, looking like this:

              QT       += core gui
              
              greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
              
              TARGET = Lightdrops
              TEMPLATE = app
              # CONFIG += console #only for debug
              
              win32 {
                  DEFINES += WIN32
                  INCLUDEPATH += C:/Dev/cfitsio_64
                  INCLUDEPATH += C:/Dev/libraw
                  INCLUDEPATH += C:\Dev\opencv\build\include
                  INCLUDEPATH += "C:\Program Files\ArrayFire\v3\include"
                  #INCLUDEPATH += C:/dev/exiv2/include
              
                  #LIBS += -LC:/Dev/exiv2/x64/Debug -llibexiv2
                  LIBS += -LC:/Dev/cfitsio_64 -lcfitsio
                  LIBS += -LC:/Dev/libraw/lib -llibraw
                  LIBS += -L"C:\Program Files\ArrayFire\v3\lib" -lafopencl
                  LIBS += -LC:\Dev\opencv\build\x64\vc14\lib -lopencv_world320
              }
              

              And more info on my projects settings in this screenshot

              Any idea?

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Did you build all the dependencies yourself ?

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                C 1 Reply Last reply
                0
                • SGaistS SGaist

                  Did you build all the dependencies yourself ?

                  C Offline
                  C Offline
                  CamelFrog
                  wrote on last edited by
                  #8

                  @SGaist Yes, using the same compiler as used in my project. Here only the Qt version changed so I don't understand why the brutal crash, I didn't change anything else.

                  1 Reply Last reply
                  0
                  • C Offline
                    C Offline
                    CamelFrog
                    wrote on last edited by
                    #9

                    Ok, I had forgotten to include 3 dlls in the directories where the executable lies.
                    In the previous version, forgetting to do such thing was throwing an error pertaining to that. Here, Qt 5.8 does not say anything in any of the output (application output, console, ...).

                    1 Reply Last reply
                    0
                    • C Offline
                      C Offline
                      CamelFrog
                      wrote on last edited by
                      #10

                      Back to the original issue:

                      The update did not change anything with the display glitch. So, the only "workaround" is to simply not use

                      ->setAttribute(Qt::WA_DeleteOnClose, true);
                      

                      This does not relate to the QMdiSubWindow on its own, but to the openGL-related children. Indeed, trying to set that attribute on the QScrollArea (which is set in the QMdiSubWindow) also reproduces the same issue:

                      currentScrollArea = new QScrollArea();
                      currentScrollArea->setWidget(rOpenGLWidget);
                      currentScrollArea->setAttribute(Qt::WA_DeleteOnClose, true);
                      

                      So as far I can see, that attributes messes with QOpenGLWidget. Any idea why? Is this attribute simply not meant to be used in that case? (i.e, having a QOpenGLWidget set in the QScrollArea or QMdiSubWindow)

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Can you provide a minimal compilable sample that produces this behaviour ? It will makes things easier to analyse and check.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        C 1 Reply Last reply
                        0
                        • SGaistS SGaist

                          Can you provide a minimal compilable sample that produces this behaviour ? It will makes things easier to analyse and check.

                          C Offline
                          C Offline
                          CamelFrog
                          wrote on last edited by
                          #12

                          @SGaist Thanks for your help. The code is rather messy, so i'm gonna try to scale the code down to the bare minimum than can reproduce this glitch. Will try to finish that in the next hours.

                          1 Reply Last reply
                          0
                          • C Offline
                            C Offline
                            CamelFrog
                            wrote on last edited by
                            #13

                            @SGaist

                            It took some time but I nailed it down a bit. So I've written the bare minimum, without the need of my OpenGL shaders (used to display the images as textures).

                            So starting from a default program with a default ui, and we put only a QMdiArea in it. Then I do this:

                            mainwindow.h

                            #ifndef MAINWINDOW_H
                            #define MAINWINDOW_H
                            
                            #include "winsockwrapper.h"
                            #include <QtCore>
                            #include <QMainWindow>
                            #include <QScrollArea>
                            #include <QMdiSubWindow>
                            #include <ropenglwidget.h>
                            
                            namespace Ui {
                            class MainWindow;
                            }
                            
                            class MainWindow : public QMainWindow
                            {
                                Q_OBJECT
                            
                            public:
                                explicit MainWindow(QWidget *parent = 0);
                                ~MainWindow();
                            
                            private:
                                Ui::MainWindow *ui;
                            
                                ROpenGLWidget *rGLWidget;
                                QScrollArea *scrollArea;
                                QMdiSubWindow *subWindow;
                            };
                            #endif // MAINWINDOW_H
                            

                            mainwindow.cpp

                            #include "mainwindow.h"
                            #include "ui_mainwindow.h"
                            
                            MainWindow::MainWindow(QWidget *parent) :
                                QMainWindow(parent),
                                ui(new Ui::MainWindow)
                            {
                                ui->setupUi(this);
                                // Size of the image to display as an openGLTexture
                                QSize oglSize(512, 512);
                                // instantiate the ROpenGLWidget (inherits QOpenGLWidget)
                                rGLWidget = new ROpenGLWidget(this);
                                // Instantiate the QSCrollArea that contains the ROpenGLWidget
                                scrollArea = new QScrollArea();
                                scrollArea->setWidget(rGLWidget);
                                // Resize it to a slightly larger size than the image itself
                                scrollArea->resize(oglSize + QSize(10, 30));
                                // Instantiate a QMdiSubWindow
                                subWindow = new QMdiSubWindow;
                                subWindow->setWidget(scrollArea);
                                ui->mdiArea->addSubWindow(subWindow);
                                /// ROpenGLWidget seems to resize only once it has been assigned to the QMdiSubWindow, not before
                                rGLWidget->resize(oglSize);
                                subWindow->resize(scrollArea->size());
                                subWindow->setAttribute(Qt::WA_DeleteOnClose, true);
                            
                                /// Not sure that's needed here
                                rGLWidget->update();
                                /// Need to show the subWindows. Does not do it by default all the time.
                                subWindow->show();
                            }
                            
                            MainWindow::~MainWindow()
                            {
                                delete ui;
                            }
                            

                            ROpenGLWidget.h

                            #include <QOpenGLBuffer>
                            #include <QOpenGLTexture>
                            
                            class QPainter;
                            class QOpenGLContext;
                            class QOpenGLPaintDevice;
                            
                            class ROpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
                            {
                                Q_OBJECT
                            public:
                                ROpenGLWidget(QWidget *parent = 0);
                                ~ROpenGLWidget();
                            
                            protected:
                                void initializeGL();
                                void resizeGL();
                                void paintGL();
                            
                            private:
                            
                                QOpenGLVertexArrayObject m_vao;
                                QOpenGLBuffer m_vertexBuffer;
                                QOpenGLBuffer m_indexBuffer;
                            };
                            
                            #endif // RopenGLWidget_H
                            

                            ROpenGLWidget.cpp

                            #include "ropenglwidget.h"
                            
                            #include <QApplication>
                            #include <QOpenGLWidget>
                            #include <QtGui/QWindow>
                            #include <QtGui/QOpenGLFunctions>
                            #include <QtGui/QOpenGLShaderProgram>
                            #include <QOpenGLVertexArrayObject>
                            #include <QOpenGLBuffer>
                            #include <QOpenGLTexture>
                            #include <QScreen>
                            
                            ROpenGLWidget::ROpenGLWidget(QWidget *parent) :
                                QOpenGLWidget(parent)
                              , m_vertexBuffer(QOpenGLBuffer::VertexBuffer)
                              , m_indexBuffer(QOpenGLBuffer::IndexBuffer)
                            {
                                    setFocusPolicy(Qt::StrongFocus);
                            }
                            
                            ROpenGLWidget::~ROpenGLWidget()
                            {
                                m_indexBuffer.destroy();
                                m_vertexBuffer.destroy();
                                m_vao.destroy();
                            }
                            
                            void ROpenGLWidget::initializeGL()
                            {
                            
                                GLfloat vertices[] = {
                                    // Positions          // Texture Coords
                                     1.0f,  1.0f, 0.0f,   1.0f, 1.0f, // Top Right
                                     1.0f, -1.0f, 0.0f,   1.0f, 0.0f, // Bottom Right
                                    -1.0f, -1.0f, 0.0f,   0.0f, 0.0f, // Bottom Left
                                    -1.0f,  1.0f, 0.0f,   0.0f, 1.0f  // Top Left
                                };
                            
                                GLuint elements[] = {  // Note that we start from 0!
                                    0, 1, 3, // First Triangle (first half of the rectangle)
                                    1, 2, 3  // Second Triangle (second half of the rectangle)
                                };
                            
                                initializeOpenGLFunctions();
                            
                                glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
                            
                                // Create Vertex Array Object
                                m_vao.create();
                                // Create Vertex Buffer Object (vbo)
                                m_vertexBuffer.create();
                                // Create the "element" or "index" buffer object
                                m_indexBuffer.create();
                            
                                // Bind VAO
                                m_vao.bind();
                            
                                // Bind Vertex Buffer + check
                                if ( !m_vertexBuffer.bind() )
                                {
                                    qWarning() << "Could not bind vertex buffer to the context";
                                    return;
                                }
                            
                                // Setup Vertex and index Buffer
                                m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
                            
                                // Send data to vertex buffer, equivalent to  glBufferData()
                                m_vertexBuffer.allocate(vertices, sizeof(vertices));
                            
                                // Bind index Buffer + check
                                if ( !m_indexBuffer.bind() )
                                {
                                    qWarning() << "Could not bind vertex buffer to the context";
                                    return;
                                }
                                m_indexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
                                // Send data to index buffer, equivalent to  glBufferData()
                                m_indexBuffer.allocate(elements, sizeof(elements));
                            
                            }
                            
                            void ROpenGLWidget::paintGL()
                            {
                            }
                            
                            void ROpenGLWidget::resizeGL()
                            {
                            }
                            

                            So whatever was in painGL() or resize was not causing the glitch. Things are caused by the destructor of ROpenGLWidget at

                            m_vao.destroy();
                            

                            and that destructor being called whenever I close the subwindow, it all comes down to that very destructor, and more precisely when destroying the vao.
                            Removing that line fixes the issue.
                            My basic openGL courses are a bit far away now, but I thought we needed to destroy the vao... If that's not the case, then ok. But if that is the case, and the vao needs to be destroyed, then why is this doing turning the whole mdiArea all black on a windows pc? Why doesn't it just make the area covered by the content of the QScrollArea all black?

                            Thanks

                            1 Reply Last reply
                            0

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved