PDA

View Full Version : [Qt4.8] QDeclarativeView in front of QGLWidget



flamaros
21st February 2013, 17:08
I am trying to display a QDeclarativeView in front of QGLWidget, to create contextual menus,...

Here is my code:


QApplication::setGraphicsSystem("opengl");

....


RenderWidget* renderWidget = new RenderWidget; // RenderWidget is the QGLWidget

QDeclarativeView *qmlView = new QDeclarativeView(renderWidget);
qmlView->setSource(QUrl::fromLocalFile("qml/main.qml"));
qmlView->setStyleSheet(QString("background: transparent"));
qmlView->setAutoFillBackground(false);
qmlView->setPalette(Qt::transparent);

QVBoxLayout *layout = new QVBoxLayout(renderWidget);
layout->setMargin(200); // reducing size to view to 3D scene behind
layout->addWidget(qmlView);

setCentralWidget(renderWidget);
resize(640,480);


With this code my qml is display in front of the 3D scene, but the layout is rendered with full opacity. When I use gDEBugger I see that the QDeclarativeView use an other openGL context than my 3D engine, and a texture containing the result of the qml view.
The texture of the qml view seems correct (with appropriate alpha zones)
I suppose the blit is completly software, when I am expecting an hardware one because I call QApplication::setGraphicsSystem("opengl"); before the QApplication initialization.

Is there a way to force the QDeclarativeView to share his opengl context with those of QGLWidget?

Added after 29 minutes:

When I remove the layout the result is exactly the same.

flamaros
27th February 2013, 10:10
Solved :

I found a simpler way to achieve my purpose. I force the application to use opengl render and register a class as QDeclarativeItem in which I put my openGL.

main.cpp:


int main(int argc, char *argv[])
{
QApplication::setGraphicsSystem("opengl");
QScopedPointer<QApplication> app(createApplication(argc, argv));

// 3D Scene Binding
qmlRegisterType<RenderItem>("RenderItem", 1, 0, "Scene3D");

// classic Qt init
QmlApplicationViewer viewer;

// update timer
QTimer repaintTimer;
QObject::connect(&repaintTimer, SIGNAL(timeout()), &viewer, SLOT(update()));
repaintTimer.setSingleShot(false);
repaintTimer.start(0);
// --

viewer.setOrientation(QmlApplicationViewer::Screen OrientationAuto);
viewer.setRenderHints(QPainter::HighQualityAntiali asing);
viewer.setResizeMode(QDeclarativeView::SizeRootObj ectToView);

viewer.setMainQmlFile(QLatin1String("qml/main.qml"));
viewer.showExpanded();

return app->exec();
}


RenderItem.h:


class RenderItem : public QDeclarativeItem
{
Q_OBJECT

public:
RenderItem(QDeclarativeItem* parent = 0)
{
// Tell to Qt Declarative that this item have to be draw
setFlag(QGraphicsItem::ItemHasNoContents, false);
}
~RenderItem();

virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->beginNativePainting();
if (!m_bGLInitialized)
// No relation of QGLWidget method (I just didn't change names)
initializeGL();

if (mWidth != width() || mHeight != height())
{
mWidth = width(); mHeight = height();
// No relation of QGLWidget method (I just didn't change names)
resizeGL(mWidth, mHeight);
}

// No relation of QGLWidget method (I just didn't change names)
paintGL();

painter->endNativePainting();
}

...

}


main.qml:


import QtQuick 1.1
import RenderItem 1.0

Rectangle {
id: main
width: 1024
height: 600

Scene3D {
anchors.centerIn: parent
anchors.fill: parent
}

...

}



Notes: If you are using FBO just take care of backup and restore the current FBO ID each frames, else you will have conflicts between your scene and qml GUI (in some cases your window can just stay white).

wysota
27th February 2013, 17:12
And all that was required was to call:


qmlView->setViewport(renderWidget);

and make sure the qmlscene doesn't clear to white.