Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[Solved] Embedding an existing GLWidget into a QML component



  • Hallo dear Qt fellows,

    Recently I've started developing with QT and QML and so far I'm quite satisfied. Now I've encountered a problem though that I cannot solve on my own. At the moment I am trying to embed an existing GLWidget into a QML component. The GLWidget shows scan data in progress (via several libraries and 3rd party code) and works well on its own. I just cannot figure out how to include it into my QML UI, so that it fits well into the interface. My interface has a side bar that is made of a bezier curve and thus is to overlap the GLWidget partly. I will provide a screenshot for clarification.

    !http://www7.pic-upload.de/02.08.11/yfcj5lc5sk1.jpg(Screenshot)!

    As you can see, the GLWidget (with black background) ought to fit under the left side bar.

    I wish there was something easy like...
    @
    Item {
    id: glwidget
    source: useMyGlwidgetFromTheCxxFiles();
    }

    Item { width: parent.width; height: parent.height
    id: leftSidebar
    }
    @
    ... or some other integration of the widget into QML or something like rendering the GLWidget onto a QML component. Just anything to make it happen :)

    Can anyone point me to a solution? I would be infinitely grateful.

    Regards,
    Franz

    PS: At the moment, the GLWidget is just placed on the window via a QVBoxLayout and setContentMargins. I hope there is a more beautiful solution.



  • You can't integrate a QGLWidget into QML, but you can use a QGLWidget as the viewport for the QML and render both the QML and the contents of the GLWidget into that viewport.



  • I think you are pointing at something along these lines:
    @
    QDeclarativeView* view = new QDeclarativeView;
    QGLFormat format = QGLFormat::defaultFormat();
    format.setSampleBuffers(false);
    QGLWidget *glWidget = new QGLWidget(format);
    glWidget->setAutoFillBackground(false);
    view->setViewport(glWidget);
    view->setSource(QUrl::fromLocalFile("ui/test.qml"));
    @

    I can tweak my code to view the given *.qml. But how can I view the GLWidget in the background of the UI?

    With the code above I can only see the QML UI. The same applies to the following code that implements the custom GLWidget.

    @
    glWidget = new GLWidget;

    // need a declarative view to display QML UI
    QDeclarativeView* view = new QDeclarativeView;//(this);

    QGLFormat format = QGLFormat::defaultFormat();
    // You can comment the next line if the graphical results are not acceptable
    format.setSampleBuffers(false);
    //QGLWidget *glWidgetx = new QGLWidget(format);
    // Comment the following line if you get display problems
    // (usually when the top-level element is an Item and not a Rectangle)
    glWidget->setAutoFillBackground(false);
    view->setViewport(glWidget);

    view->setSource(QUrl::fromLocalFile("ui/test.qml"));
    view->setResizeMode(QDeclarativeView::SizeRootObjectToView);

    view->setGeometry(100,100,800,600);
    //view.show();
    setCentralWidget(view);
    @

    I can only see my GLWidget (but on top, not in the background) when I attach it to a layout through addWidget like this:

    @
    QDeclarativeView* view = new QDeclarativeView(this);
    view->setSource(QUrl::fromLocalFile("ui/test.qml"));
    view->setResizeMode(QDeclarativeView::SizeRootObjectToView);
    view->setGeometry(100,100,800,600);
    //view.show();
    setCentralWidget(view);
    glWidget = new GLWidget;
    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->setContentsMargins(220, 80, 170, 0);
    mainLayout->addWidget(glWidget);
    centralWidget()->setLayout(mainLayout);
    @

    I would be eternally grateful if someone could point me to a solution. I've been searching for days now and can't figure it out.

    It should be like this (with | being semi-transparent or *.png overlays as visible in the picture above):
    Viewer <) QML-UI | GLWidget || MainWindow

    and not like this:
    Viewer <) GLWidget | QML-UI || MainWindow.

    Pleeease help.



  • Take the OpenGL rendering code from the GLWidget and put it in a QDeclarativeItem. Use this custom QDeclarativeItem in the QML.



  • [quote author="Bradley" date="1312320568"]Take the OpenGL rendering code from the GLWidget and put it in a QDeclarativeItem. Use this custom QDeclarativeItem in the QML.
    [/quote]
    Do you mean the code in paintGL()? What about the other code (e.g. event handling?)

    I think what you mean is something like this:
    http://developer.qt.nokia.com/forums/viewthread/4109/

    I will try that as soon as possible and report how it went.



  • Still not working. I did what you told me, although I don't quite know how to use the custom item in the QML. I have implemented the linked example to have a small project with no collateral influences. There are no build or runtime errors, I just cannot see the content (except the standard rectangle). I will post my code for reference. When I change positions of MDE and Rectangle in the .qml, only white background appears.

    What am I doing wrong?

    Header:
    @
    #ifndef QWIDGETS_HPP
    #define QWIDGETS_HPP

    #include <QDeclarativeItem>
    #include <QGLWidget>

    class MDE : public QDeclarativeItem
    {
    Q_OBJECT

    public:
    MDE(QDeclarativeItem *parent = 0);
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
    };

    #endif // QWIDGETS_HPP
    @

    Source:
    @
    #include "GLItem.h"
    #include <QApplication>
    #include <QDeclarativeView>

    MDE::MDE(QDeclarativeItem *parent )
    {
    setFlag(QGraphicsItem::ItemHasNoContents, false);
    }

    void MDE::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
    painter->beginNativePainting();
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glBegin(GL_QUADS);
    glColor3ub(0,0,255);
    glVertex2d(-0.75,-0.75);
    glVertex2d(-0.75,0.75);
    glColor3ub(255,0,0);
    glVertex2d(0.75,0.75);
    glVertex2d(0.75,-0.75);
    glEnd();
    painter->endNativePainting();
    }

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

    qmlRegisterType<MDE>("MDEPlugins", 1, 0, "MDE");

    QDeclarativeView view;
    QGLWidget *glWidget = new QGLWidget;
    view.setViewport(glWidget);
    view.setSource(QUrl::fromLocalFile("my.qml"));
    view.show();
    return app.exec();
    }
    @

    QML:
    @
    import QtQuick 1.0
    import MDEPlugins 1.0

    Item { width: 400; height: 300

    MDE { width: 300; height: 200

    }

    Rectangle { width: 200; height: 100
    anchors.right:parent.right
    color: "blue"
    }

    }
    @



  • Try this

    @
    void MDE::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
    painter->beginNativePainting();
    glBegin(GL_QUADS);
    glColor3ub(0,0,255);
    glVertex2d(boundingRect().left(), boundingRect().top());
    glVertex2d(boundingRect().right(), boundingRect().top());
    glColor3ub(255,0,0);
    glVertex2d(boundingRect().right(), boundingRect().bottom());
    glVertex2d(boundingRect().left(), boundingRect().bottom());
    glEnd();
    painter->endNativePainting();
    }
    @



  • Wow, it works!! What happened? Was the GL code wrong?

    Anyway, I tried it with my custom code and - after some minor fiddling - it works, too! Oh dear, I could kiss you right now :D After many hours of testing, it finally works as intended. You saved me countless hours and made a sweet sweet UI possible.

    THANK YOU!



  • Yes, the GL code was wrong. It was clearing the buffer and it was assuming a different coordinate system. I removed the calls to glClear and glIdentity and changed the vertices.


Log in to reply