[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
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.