{"id":160,"date":"2010-11-30T09:59:33","date_gmt":"2010-11-30T16:59:33","guid":{"rendered":"http:\/\/www.lothlorien.com\/kf6gpe\/?p=160"},"modified":"2011-02-21T15:49:12","modified_gmt":"2011-02-21T22:49:12","slug":"adding-c-objects-to-your-qml","status":"publish","type":"post","link":"https:\/\/www.lothlorien.com\/kf6gpe\/adding-c-objects-to-your-qml\/","title":{"rendered":"Adding C++ Objects to your QML"},"content":{"rendered":"<p>There&#8217;s many times that you may want to access a C++ object from your QML. One obvious example is if you&#8217;ve already written a data model in C++; you can leverage that model with QML-based user interface. Any other time you need to access things you can only touch from C++, like hardware integration not provided by Qt Mobility, is another example.<\/p>\n<p>As a simple example, consider a case where you want to expose a C++-based application controller (think model-view-controller) to your QML. You&#8217;ve got a class, <code>AppController<\/code>, with some Qt metaobject invocable methods, either expressed as properties, slots or using <code>Q_INVOKABLE<\/code>. Mine looks like this:<\/p>\n<pre>\r\nclass AppController : public QObject\r\n{\r\n    Q_OBJECT\r\n    Q_PROPERTY(int width READ width NOTIFY sizeChanged)\r\n    Q_PROPERTY(int height READ height NOTIFY sizeChanged)\r\n\r\npublic:\r\n    explicit AppController(QObject *parent = 0);\r\n    void setSize(const QSize& size) { mSize = size; emit sizeChanged(); };\r\n    int width() { return mSize.width(); };\r\n    int height() { return mSize.height(); };\r\n\r\n   Q_INVOKABLE void magicInvocation();\r\n\r\nsignals:\r\n    void sizeChanged();\r\n\r\nprivate:\r\n    QSize mSize;\r\n};\r\n\r\n<\/pre>\n<p>Because QML binds using Qt&#8217;s metaobject system, the C++ object you want to expose to QML must be a descendant of <code>QObject<\/code>. Our <code>AppController<\/code> class is pretty simple; it&#8217;s just carrying the size of the window displaying the QML view, along with some C++ method my QML invokes named <code>magicInvocation<\/code>. (If I told you what it did&#8230; you get the idea.)<\/p>\n<p>Of course, we need to fire up a QML viewer with our QML, and add an instance of <code>AppController<\/code> to the object hierarchy in the QML engine. I do that in my application&#8217;s <code>main<\/code>, which looks like this:<\/p>\n<pre>\r\nint main(int argc, char *argv[])\r\n{\r\n    QApplication app(argc, argv);\r\n\r\n    QRect screen = QApplication::desktop()->screenGeometry();\r\n    QMainWindow* window = new QMainWindow(0, Qt::FramelessWindowHint );\r\n    QDeclarativeView* view = new QDeclarativeView(window);\r\n    AppController* controller(window);\r\n\r\n    \/\/ The only thing we show is the declarative view.\r\n    window->setCentralWidget(&view);\r\n\r\n    \/\/ Size the window to be as big as it can be, except we don't\r\n    \/\/ want it too big on our dev workstations.\r\n    if (screen.width() &lt;= kDesiredWidth) {\r\n        window->showMaximized();\r\n    } else {\r\n        window->setGeometry(QRect(\r\n            (screen.width()-kDesiredWidth)\/2, (screen.height()-kDesiredHeight)\/2, \r\n            kDesiredWidth, kDesiredHeight));\r\n        window->show();\r\n    }\r\n    controller.setSize(window.size());\r\n\r\n    \/\/ Proxy in our app controller so QML get its properties and show our QML\r\n    view->rootContext()->setContextProperty(\"controller\", controller);\r\n    view->setSource(QUrl(\"qml\/main.qml\"));\r\n\r\n    int result =  app.exec();\r\n    delete window;\r\n    return result;\r\n}\r\n\r\n<\/pre>\n<p>Pretty basic stuff here:<\/p>\n<ol>\n<li>I get the screen size, used by the <code>AppController<\/code> for its own nefarious purposes.<\/li>\n<li>I create a full-screen main window with no window chrome.<\/li>\n<li>I create a <code>QDeclarativeView<\/code> to display the QML, and make the main window&#8217;s main widget the new <code>QDeclarativeView<\/code>.<\/li>\n<li>I create an instance of <code>AppController<\/code>.\n<li>I do some funny stuff with the main window&#8217;s size so I don&#8217;t go crazy working on my desktop&#8217;s 22&#8243; monitor, restricting the maximum possible size of the main window for test purposes.<\/li>\n<li>Using the <code>QDeclarativeView<\/code>&#8216;s <code>QDeclarativeEngine<\/code>, I add the <code>AppController<\/code> instance to the QML context, giving it the name <code>controller<\/code>. <\/li>\n<li>I set the initial source of the QML to the QML entry point for my user interface, included as a file in my application&#8217;s package (not as a resource, but you could also choose to package it as a Qt application resource if you want.)<\/li>\n<li>Finally, I pass control to <code>QApplication<\/code>&#8216;s main loop, and return its result code when its event loop exits.\n<\/ol>\n<p>The magic is <code>QDeclarativeEngine::setContextProperty<\/code>, which binds a <code>QObject<\/code>-derived instance to a specific name in the QML context. Once I do this, in my QML I can access this just as I would any QML or JavaScript object; its name is <code>controller<\/code>. So I might write <code>controller.magicInvocation()<\/code> to invoke my magic function in an <code>onPressed<\/code> signal handler, for instance.<\/p>\n<p>(This is well-documented, but I found it handy to break this point out into a separate example to refer to. It&#8217;s also a predecessor for several upcoming posts, so it&#8217;s here so that those posts can refer back to this one.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There&#8217;s many times that you may want to access a C++ object from your QML. One obvious example is if you&#8217;ve already written a data model in C++; you can leverage that model with QML-based user interface. Any other time you need to access things you can only touch from C++, like hardware integration not &hellip; <a href=\"https:\/\/www.lothlorien.com\/kf6gpe\/adding-c-objects-to-your-qml\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Adding C++ Objects to your QML<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,9],"tags":[21,20],"class_list":["post-160","post","type-post","status-publish","format-standard","hentry","category-mobile","category-programming","tag-qml","tag-qt"],"_links":{"self":[{"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/posts\/160","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/comments?post=160"}],"version-history":[{"count":23,"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/posts\/160\/revisions"}],"predecessor-version":[{"id":324,"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/posts\/160\/revisions\/324"}],"wp:attachment":[{"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/media?parent=160"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/categories?post=160"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lothlorien.com\/kf6gpe\/wp-json\/wp\/v2\/tags?post=160"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}