Can't link QOpenGLWidget into a Form



  • Hi guys, I have an application that uses QOpenGLWidget to show a scene.
    Now, I want to add an interface to it so I created a Form and I added to it a QOpenGLWidget element:
    0_1559812653219_Captura2.PNG

    Now I am trying to link the QOpenGLWidget I had created to this QOpenGlWidget that is into the Form but I cant. It shows a black screen.

    This is the main class where I initialized the QOpenGLWidget:

    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        QSurfaceFormat format;
        format.setDepthBufferSize(24);
        format.setStencilBufferSize(8);
        format.setVersion(4, 1);
        format.setProfile(QSurfaceFormat::CoreProfile);
        QSurfaceFormat::setDefaultFormat(format);
    
        glwindow *ventana = new glwindow();
        ventana->setFormat(format);
        ventana->show();
        std::cout<<"Ventana lanzada"<<std::endl;
        ventana->setMouseTracking(true);
        ventana->installEventFilter(ventana);
    

    That shows me a window like this:
    0_1559812840644_Captura3.PNG

    Now I added code to link this window to the frame I have created:
    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setVersion(4, 1);
    format.setProfile(QSurfaceFormat::CoreProfile);
    QSurfaceFormat::setDefaultFormat(format);
    
    glwindow *ventana = new glwindow();
    ventana->setFormat(format);
    ventana->show();
    std::cout<<"Ventana lanzada"<<std::endl;
    Form *ui = new Form();
    ui->setQOpenGLWindow(ventana);
    ui->show();
    ventana->setMouseTracking(true);
    ventana->installEventFilter(ventana);
    

    and this is the result. On the left there is the form and on the right there is the window that I shown you before.
    0_1559812990376_Captura.PNG
    The black screen is a QOpenGLWidget that should show what is in the right window.
    What is happening?
    I leave here the form classes too:

    #ifndef FORM_H
    #define FORM_H
    
    #include <QWidget>
    #include "glwindow.h"
    
    namespace Ui {
    class Form;
    }
    
    class Form : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Form(QWidget *parent = nullptr);
        void setQOpenGLWindow(glwindow *window);
        ~Form();
    
    private:
        Ui::Form *ui;
    };
    
    #endif // FORM_H
    
    
    #include "form.h"
    #include "ui_form.h"
    
    Form::Form(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Form)
    {
        ui->setupUi(this);
    
    }
    
    void Form::setQOpenGLWindow(glwindow *window)
    {
        ui->openGLWidget = window;
    }
    Form::~Form()
    {
        delete ui;
    }
    
    

  • Lifetime Qt Champion

    Hi,

    You are just replacing a pointer. That won't automagically replace the original widget by yours.

    You should rather use the promote feature.



  • @SGaist ok now I added a promote to my class glwindow which is the QopenglWidget class and my app crashes.
    It says :
    0_1559908685844_Captura.PNG
    This is my glwindow.cpp:

    #include "glwindow.h"
    
    glwindow::glwindow(QWidget *parent): QOpenGLWidget (parent)
    {
    
    }
    glwindow::~glwindow()
    {
    
    }
    
    void glwindow::initializeGL()
        {
            // Set up the rendering context, load shaders and other resources, etc.:
           initializeOpenGLFunctions();
           printContextInformation();
           glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    
           // - Le decimos a OpenGL que tenga en cuenta la profundidad a la hora de dibujar.
           // No tiene por qué ejecutarse en cada paso por el ciclo de eventos.
           glEnable(GL_DEPTH_TEST);
           glDepthFunc(GL_LEQUAL);
        }
    
    void glwindow::paintGL()
    {
           // Draw the scene:
           glClear(GL_COLOR_BUFFER_BIT);
           renderer::getInstance()->dibujar();
    
    }
    
     void glwindow::resizeGL(int w, int h)
     {
         renderer::getInstance()->redimensionarAreaDibujo(w,h);
         window_refresh();
     }
    
     bool glwindow::eventFilter(QObject *obj, QEvent *event)
     {
    
       if (event->type() == QEvent::KeyPress)
       {
         QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
    
         if(keyEvent->key()==Qt::Key_Escape)
         {
             this->close();
         }
         if(keyEvent->key()==Qt::Key_P)
         {
             renderer::getInstance()->setModoDibujo(0);
         }
         if(keyEvent->key()==Qt::Key_W)
         {
             renderer::getInstance()->setModoDibujo(1);
         }
         if(keyEvent->key()==Qt::Key_T)
         {
             renderer::getInstance()->setModoDibujo(2);
         }
         if(keyEvent->key()==Qt::Key_A)
         {
             renderer::getInstance()->setModoDibujo(3);
         }
         if(keyEvent->key()==Qt::Key_Z)
         {
             renderer::getInstance()->setModoDibujo(4);
         }
         if(keyEvent->key()==Qt::Key_X)
         {
             renderer::getInstance()->setModoDibujo(5);
         }
         if(keyEvent->key()==Qt::Key_C)
         {
             renderer::getInstance()->setModoDibujo(6);
         }
         if(keyEvent->key()==Qt::Key_V)
         {
             renderer::getInstance()->setModoDibujo(7);
         }
         if(keyEvent->key()==Qt::Key_J)
         {
             renderer::getInstance()->setModoTextura(false);
         }
         if(keyEvent->key()==Qt::Key_K)
         {
             renderer::getInstance()->setModoTextura(true);
         }
         if(keyEvent->key()==Qt::Key_1)
         {
             renderer::getInstance()->camaraSiguiente();
         }
         if(keyEvent->key()==Qt::Key_2)
         {
             renderer::getInstance()->camaraAnterior();
         }
         if(keyEvent->key()==Qt::Key_N)
         {
             float posX, posY, posZ,lookX,lookY,lookZ,fovX;
             std::cout << "Proceso de creacion de una nueva camara virtual" << std::endl;
             std::cout << "Por favor, especifique su posicion en los ejes: " << std::endl;
             std::cout << "Eje X: ";
             std::cin >> posX;
             std::cout << std::endl;
             std::cout << "Eje Y: ";
             std::cout << std::endl;
             std::cin >> posY;
             std::cout << "Eje Z: ";
             std::cin >> posZ;
             std::cout << std::endl;
             std::cout << "Especifique hacia donde desea mirar: " << std::endl;
             std::cout << "Eje X: ";
             std::cin >> lookX;
             std::cout << std::endl;
             std::cout << "Eje Y: ";
             std::cin >> lookY;
             std::cout << std::endl;
             std::cout << "Eje Z: ";
             std::cin >> lookZ;
             std::cout << std::endl;
             std::cout << "Por ultimo especifique su angulo de vision: " << std::endl;
             std::cout << "Angulo de vision: ";
             std::cin >> fovX;
             renderer::getInstance()->crearCamara(QVector3D(posX, posY, posZ), QVector3D(lookX, lookY, lookZ), fovX);
         }
         if(keyEvent->key()==Qt::Key_Alt)
         {
             pan = true;
         }
         if(keyEvent->key()==Qt::Key_Control)
         {
             tilt=true;
         }
         if(keyEvent->key()==Qt::Key_Right)
         {
             renderer::getInstance()->moverCamara(TRUCK, 0.3f);
         }
         if(keyEvent->key()==Qt::Key_Left)
         {
             renderer::getInstance()->moverCamara(TRUCK, -0.3f);
         }
         if(keyEvent->key()==Qt::Key_Up)
         {
             renderer::getInstance()->moverCamara(CRANE, -0.3f);
         }
         if(keyEvent->key()==Qt::Key_Down)
         {
             renderer::getInstance()->moverCamara(BOOM, 0.3f);
         }
         if(keyEvent->key()==Qt::Key_F1)
         {
             renderer::getInstance()->moverCamara(DOLLY, -0.3f);
         }
         if(keyEvent->key()==Qt::Key_F2)
         {
             renderer::getInstance()->moverCamara(DOLLY, 0.3f);
             std::cout<<"Realizando DOLLY"<<std::endl;
         }
    
         window_refresh();
         return true;
       }
       if (event->type() == QEvent::KeyRelease)
       {
              pan = false;
              tilt = false;
              window_refresh();
              return true;
       }
       if(event->type() == QEvent::MouseButtonPress)
       {
            arrastrar = true;
            window_refresh();
            return true;
       }
       if(event->type() == QEvent::MouseButtonRelease)
       {
            arrastrar = false;
            window_refresh();
            return true;
       }
       if(event->type() == QEvent::Wheel)
       {
           QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
           if(wheelEvent->delta()> 0)
           {
               renderer::getInstance()->modificarZoom(-2);
           }else
           {
               renderer::getInstance()->modificarZoom(2);
           }
    
           window_refresh();
           return true;
       }
       if(event->type() == QEvent::MouseMove)
       {
           QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
           int xpos = mouseEvent->x();
           int ypos = mouseEvent->y();
           if (arrastrar)
                {
                    if (pan)
                    {
                        renderer::getInstance()->moverCamara(PAN, (posX - xpos)/2);
                        posX = xpos;
                        posY = ypos;
    
                    }
                    else if (tilt)
                    {
                        renderer::getInstance()->moverCamara(TILT, (posY - ypos)/2);
                        posX = xpos;
                        posY = ypos;
    
                    }
                    else
                    {
                        renderer::getInstance()->moverCamara(ORBIT_HORIZONTAL, (xpos - posX));
                        renderer::getInstance()->moverCamara(ORBIT_VERTICAL, ((ypos - posY) / 2));
                        posX = xpos;
                        posY = ypos;
                    }
                }
                else {
                    posX = xpos;
                    posY = ypos;
                }
           window_refresh();
           return true;
       }
    
       return QObject::eventFilter(obj, event);
     }
    
     void glwindow::window_refresh()
     {
         renderer::getInstance()->refreshCallback();
         update();
     }
    
     void glwindow::printContextInformation()
     {
       QString glType;
       QString glVersion;
       QString glProfile;
    
       // Get Version Information
       glType = (context()->isOpenGLES()) ? "OpenGL ES" : "OpenGL";
       glVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
    
       // Get Profile Information
     #define CASE(c) case QSurfaceFormat::c: glProfile = #c; break
       switch (format().profile())
       {
         CASE(NoProfile);
         CASE(CoreProfile);
         CASE(CompatibilityProfile);
       }
     #undef CASE
    
       // qPrintable() will print our QString w/o quotes around it.
       qDebug() << qPrintable(glType) << qPrintable(glVersion) << "(" << qPrintable(glProfile) << ")";
     }
    
    

    and this is the code of the binding:

    bool shaderProgram::use() {
        // Antes de activar un shader program para su uso, hay que comprobar
         // si se ha creado bien y se ha enlazado bien
        if ((handler) && (linked)) {
            shaderP->bind();
            return true;
        }
        else {
            std::cout << "Cannot use shader program";
            return false;
        }
    }
    

    Without the promote added it works in a different window as you can see in my first post but now I think I have to d something with the context but I dont know what.

    Thanks


  • Lifetime Qt Champion

    In that case, let's take another way. Put a layout in your UI and add your OpenGL widget to it. This will likely be simpler in the short run.



  • @SGaist How an I add my OpenGLWIdget to the UI instead of adding an empty one?. I am adding the widgets from here:
    0_1560237605948_Captura.PNG

    It has to be something with the context, I was not using any function related with the context when I hadn't the UI but It seems that now I need to use it and I don't know how.


  • Qt Champions 2018

    @JesusM said in Can't link QOpenGLWidget into a Form:

    How an I add my OpenGLWIdget to the UI instead of adding an empty one?

    @SGaist suggested to do it in your code manually (not using Designer).



  • @jsulm ok I will try it now.



  • @SGaist ok, It works but it creates the widget at the bottom:
    0_1560240438164_Captura.PNG

    and I need to have it on the left side, as I had it before creating it manually:
    0_1560240464315_captura2.PNG
    This is my hierarchy (with the empty QOpenGLWidget):
    0_1560240518121_Captura3.PNG
    I added the widget to the centralWidget which has a grid layout. With the Qt Designer I just needed to drag my widget to the left margin to move it to the left but now I can't do it as I created the widget by code.


  • Qt Champions 2018

    @JesusM said in Can't link QOpenGLWidget into a Form:

    I added the widget to the centralWidget

    You should add it to the layout at desired position.



  • @jsulm this is the layout where I want to add it. I had the QOpenGLWidget in that layout and it was ok as you can see in the second image.


  • Qt Champions 2018

    @JesusM I'm a bit lost now. You should remove that QOpenGLWidget you added in the Designer and instead add one via code and insert it in same layout.



  • @jsulm I think I didn't explain myself well, sorry. The hierarchy that I posted is before I added the QOpenGLWidget by code, just to show you where I had it added. When I added it by code I removed that component from the Qt Designer so, now, my hierarchy in the Qt Designer hasn't got that component.

    I added this code to the constructor of my UI to add the QOpenGLWidget:

    QSurfaceFormat format;
        format.setDepthBufferSize(24);
        format.setStencilBufferSize(8);
        format.setVersion(4, 1);
        format.setProfile(QSurfaceFormat::CoreProfile);
        QSurfaceFormat::setDefaultFormat(format);
    
        glwindow *ventana = new glwindow();
        ventana->setFormat(format);
        ventana->show();
        ventana->setMouseTracking(true);
        ventana->installEventFilter(ventana);
        std::cout<<"Ventana lanzada"<<std::endl;
        ui->gridLayout->addWidget(ventana);
    

    This code add the QOpenGLWidget but at the bottom of the grid layout.


  • Qt Champions 2018

    @JesusM said in Can't link QOpenGLWidget into a Form:

    ui->gridLayout->addWidget(ventana);

    You don't specify where exactly you want this widget to be in the layout. Take a look at https://doc.qt.io/qt-5/qgridlayout.html#addWidget



  • @jsulm all the values I have tried make my program crash. I think I don't understand well how to use the addWidget function.
    I tried all of this:

    ui->gridLayout->addWidget(ventana,0,0); // This doesn't crash but the widget is still at the bottom;
        ui->gridLayout->addWidget(ventana,1,0); //Same here
    //From here all make my program crash.
        ui->gridLayout->addWidget(ventana,0,1);
        ui->gridLayout->addWidget(ventana,1,1);
        ui->gridLayout->addWidget(ventana,0,0, Qt::AlignLeft);
        ui->gridLayout->addWidget(ventana,0,1, Qt::AlignLeft);
        ui->gridLayout->addWidget(ventana,1,0, Qt::AlignLeft);
        ui->gridLayout->addWidget(ventana,1,1, Qt::AlignLeft);
    


  • I found the solution. I had to set the QSizePolicy of my widget and then place the widget at the top-left side:

        ventana->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Expanding);
        ui->gridLayout->addWidget(ventana,0,0);
    

    0_1560257501850_Captura.PNG

    Thanks all for helping :)


Log in to reply