http://www.ics.com/blog/combining-qt-widgets-and-qml-qwidgetcreatewindowcontainer
Introduction
Qt 5.1 introduces a new method in the QWidget class called createWindowContainer(). It allows embedding a QWindow (such as a QQuickView) into a QWidget-based application. This allows combining both QML and widgets in the same application, something that was not possible with Qt 5.0.
The new method is well documented (see References at the end of the posting) but I did not see any complete compilable examples of using it, so I thought I would present one here.
The new API provides the following static method:
QWidget *QWidget::createWindowContainer(QWindow *window, QWidget *parent=0, Qt::WindowFlags flags=0)
The window parameter can be a QQuickView, since it is derived from QWindow. The created window container will be a child of the parent widget and takes over ownership of the QWindow. The QWindow can be removed from the window container with a call to QWindow::setParent().
Once the window has been embedded into the container, it will control the window's geometry and visibility. Explicit calls to QWindow::setGeometry(), QWindow::show() or QWindow::hide() on an embedded window are not recommended.
I started the example by using Qt Creator's new project wizard to create a Qt GUI application with a UI class derived from QMainWindow and a Qt Designer form. The main program, main.cpp, and window class header file mainwindow.h, were unchanged from what Qt Creator generated.
In the implementation of the UI class in mainwindow.cpp, we need to create a QQuickView and then call QWidget::createWindowContainer(), passing in the view and the parent widget. This returns a QWidget that we can add to the UI layout. I set the minimum and maximum size of the view widget and set the focus policy (see the later discussion on focus handling). Shown below is the code with the relevant lines highlighted.
#include <QQuickView> #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect(ui->pushButton, SIGNAL(clicked()), qApp, SLOT(quit())); QQuickView *view = new QQuickView(); QWidget *container = QWidget::createWindowContainer(view, this); container->setMinimumSize(200, 200); container->setMaximumSize(200, 200); container->setFocusPolicy(Qt::TabFocus); view->setSource(QUrl("main.qml")); ui->verticalLayout->addWidget(container); } MainWindow::~MainWindow() { delete ui; }
The Qt designer form I created arbitrarily included a QLineEdit and a QPushButton to show some representative widgets.
I created a simple QML file which displays a red rectangle and some text. To illustrate some things that are typically done in QML I added a rotation animation of text in the rectangle, which can be paused and resumed by clicking on it.
The listing for the QML file is below. It will run as usual on its own using qmlscene if desired.
import QtQuick 2.1 Rectangle { id: rectangle color: "red" width: 200 height: 200 Text { id: text text: "This is QML code.\n(Click to pause)" font.pointSize: 14 anchors.centerIn: parent PropertyAnimation { id: animation target: text property: "rotation" from: 0; to: 360; duration: 5000 loops: Animation.Infinite } } MouseArea { anchors.fill: parent onClicked: animation.paused ? animation.resume() : animation.pause() } Component.onCompleted: animation.start() }
A screen shot of the application running is shown below.
The complete source code for the example can be downloaded from here.
There are currently some limitations, which are described in the documentation:
The examples given in this blog post have shown how to combine a QML view with widgets in the same application. This new feature of Qt 5.1 opens up new possibilities for using QML in QWidget-based applications.
Comments
additional magic needed for android
Submitted by zing0000 on Thu, 12/19/2013 - 19:02I tried this example in Qt5.2 for android. It builds and deploys but crashes because it cannot find main.qml.
So I tried using the Qt resource system,
view->setSource(QUrl("qrc:/main.qml"));
but now it crashes with,
W/Adreno-EGL(28315): <qeglDrvAPI_eglMakeCurrent:2918>: EGL_BAD_MATCH
E/libEGL (28315): eglMakeCurrent:775 error 3009 (EGL_BAD_MATCH)
W/Qt (28315): eglconvenience\qeglplatformcontext.cpp:119 (virtual bool QEGLPlatformContext::makeCurrent(QPlatformSurface*)): QEGLPlatformContext::makeCurrent: eglError: 3009, this: 0x74f37328
W/Qt (28315):
D/dalvikvm(28315): GC_CONCURRENT freed 422K, 5% free 9166K/9620K, paused 3ms+8672ms, total 13285ms
Debugging has finished
'org.qtproject.example.widgetsandqml' terminated.
I am trying to get my own windowcontainer app to work in android and thought this simple example would help.
But looks like there are problems here too.
Any ideas?
Re: additional magic needed for android
Submitted by jtranter on Fri, 12/20/2013 - 09:51I don't currently have access to Qt in an Android device, but I'll ask around here and see if one of my colleagues does. I saw the discussion about this on the qt-project.org forums, which lead to no solution. I suggest you ask on the [email protected] mailing list, as more people tend to follow the mailing lists than the forums.
Re: additional magic needed for android
Submitted by jtranter on Fri, 12/20/2013 - 15:19A colleague confirmed seeing a similar error on his Android device. It appears that this is not supported on Android due to a limition that Qt on Android only supports one OpenGL surface. I'm told that there has been talk about removing this restriction but there is no workaround at the moment.
White screen when integrating qml into widget
Submitted by lennart on Wed, 01/22/2014 - 23:56Hi, and thanks for a great example!
I have used it as a base in my effort to gradually convert some of our software from classic widget over to qml. However we have struck on some serious problems that we need help with fixing.
Sometimes* the qml renders fine and everything is dandy.
Sometimes in this case means any combination of the following:
+ On some computers
+ On some operating systems
+ On some graphics hardware
+ Using some graphics drivers
+ Using some version of Qt
What happens when it is NOT working is that the entire qml rendering area is white. There are no error messages or crashes or anything usefull to go by except that it is rendered completely white. My hunch is that this might do some strange things that does not fare well with some buggy drivers.
I realize that this is not a problem you can give me a solution to in an instant, but what I am looking for are tips as to how we can pinpoint what happens? How can we lure out some debugging information that we can use?
Thanks!
Re: White screen when integrating qml into widget
Submitted by jtranter on Mon, 01/27/2014 - 14:22I polled some of our developers about this and here are some suggestions they had:
Make sure debug output is enabled and going somewhere that you can see it.
First check if the QML view being white behavior happens with the simplest possible mixed QML/QWidget app (and not a full featured app you are working on).
See if it happens with a plain QML-only app (i.e. a bare QQmlScene or the standard Creator QML project) loading a simple QML main program.
Check the behavior when running from within Qt Creator/build environment or from a folder where every dependent library has been placed. It could be a Qt version incompatibility of some sort, with the application attempting to load the wrong libraries.
Do you do any custom OpenGL rendering of QML items, or interact with the QML scenegraph from C++ in any way?
Having the list of platforms where the application fails would be helpful if you can share it with us.