Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Qt5 C++ GUI Programming Cookbook

You're reading from   Qt5 C++ GUI Programming Cookbook Design and build a functional, appealing, and user-friendly graphical user interface

Arrow left icon
Product type Paperback
Published in Jul 2016
Publisher Packt
ISBN-13 9781783280278
Length 300 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Lee Zhi Eng Lee Zhi Eng
Author Profile Icon Lee Zhi Eng
Lee Zhi Eng
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. Look and Feel Customization FREE CHAPTER 2. States and Animations 3. QPainter and 2D Graphics 4. OpenGL Implementation 5. Building a Touch Screen Application with Qt5 6. XML Parsing Made Easy 7. Conversion Library 8. Accessing Databases 9. Developing a Web Application Using Qt Web Engine Index

Exposing QML object pointer to C++

Sometimes we want to modify the properties of a QML object through C++ scripting, such as changing the text of a label, hiding/showing the widget, changing its size, and so on. Qt's QML engine allows you to register your QML objects to C++ types which automatically exposes all its properties.

How to do it…

We want to create a label in QML and change its text occasionally. In order to expose the label object to C++, we can do the following steps. First, create a C++ class called MyLabel that extends from QObject class:

mylabel.h:
class MyLabel : public QObject
{
  Q_OBJECT
  public:
    // Object pointer
    QObject* myObject;

    explicit MyLabel(QObject *parent = 0);

  // Must call Q_INVOKABLE so that this function can be used in QML
  Q_INVOKABLE void SetMyObject(QObject* obj);
}

In the mylabel.cpp source file, define a function called SetMyObject() to save the object pointer. This function will later be called in QML:

mylabel.cpp:
void MyLabel::SetMyObject(QObject* obj)
{
  // Set the object pointer
  myObject = obj;
}

After that, in main.cpp, include MyLabel header and register it to QML engine using the function qmlRegisterType():

#include "mylabel.h"
int main(int argc, char *argv[])
{
  // Register your class to QML
  qmlRegisterType<MyClass>("MyLabelLib", 1, 0, "MyLabel");
}

Notice that there are four parameters you need to declare in qmlRegisterType(). Besides declaring your class name (MyLabel), you also need to declare your library name (MyLabelLib) and its version (1.0), which will be used for importing your class to QML later on.

Now that the QML engine is fully aware of our custom label class, we can then map it to our label object in QML and import the class library we defined earlier by calling import MyLabelLib 1.0 in our QML file. Notice that the library name and its version number have to match with the one you declared in main.cpp, otherwise it will throw you an error.

After declaring MyLabel in QML and setting its ID as mylabels, call mylabel.SetMyObject(myLabel) to expose its pointer to C/C++ right after the label is being initialized:

import MyLabelLib 1.0

ApplicationWindow
{
  id: mainWindow
  width: 480
  height: 640

  MyLabel
  {
    id: mylabel
  }

  Label
  {
    id: helloWorldLabel
    text: qsTr("Hello World!")
    Component.onCompleted:
    {
      mylabel.SetMyObject(hellowWorldLabel);
    }
  }
}

Please be aware that you need to wait until the label is fully initiated before exposing its pointer to C/C++, otherwise you may cause the program to crash. To make sure it's fully initiated, call SetMyObject() within Component.onCompleted and not any other places.

Now that the QML label has been exposed to C/C++, we can change any of its properties by calling setProperty() function. For instance, we can set its visibility to true and change its text to Bye bye world!:

// QVariant automatically detects your data type
myObject->setProperty("visible", QVariant(true));
myObject->setProperty("text", QVariant("Bye bye world!"));

Besides changing the properties, we can also call its functions by calling QMetaObject::invokeMethod():

QVariant returnedValue;
QVariant message = "Hello world!";

QMetaObject::invokeMethod(myObject, "myQMLFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, message));

qDebug() << "QML function returned:" << returnedValue.toString();

Or simply, we can call the invokedMethod() function with only two parameters if we do not expect any values to be returned from it:

QMetaObject::invokeMethod(myObject, "myQMLFunction");

How it works...

QML is designed to be easily extensible through C++ code. The classes in the Qt QML module enable QML objects to be loaded and manipulated from C++, and the nature of the QML engine's integration with Qt's meta object system enables C++ functionality to be invoked directly from QML. To provide some C++ data or functionality to QML, it must be made available from a QObject-derived class.

QML object types can be instantiated from C++ and inspected in order to access their properties, invoke their methods, and receive their signal notifications. This is possible due to the fact that all QML object types are implemented using QObject-derived classes, enabling the QML engine to dynamically load and introspect objects through the Qt meta object system.

You have been reading a chapter from
Qt5 C++ GUI Programming Cookbook
Published in: Jul 2016
Publisher: Packt
ISBN-13: 9781783280278
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime