Qt Quick How-tos

This page aims to provide an easily discoverable, useful reference that shows the simplest and best way of performing specific tasks in Qt Quick. Each solution provides QML and/or C++ code snippets where applicable, and every snippet is automatically tested by Qt to ensure they remain functional.

How do I:

Call a C++ function from QML when a Button is clicked

Assuming that the C++ type should be globally available to the QML files in the application, the simplest way is to make it a QML singleton with QML_SINGLETON. For example, in the header file, backend.h:

 #include <QObject>
 #include <QQmlEngine>

 class Backend : public QObject
 {
     Q_OBJECT
     QML_ELEMENT
     QML_SINGLETON

 public:
     Q_INVOKABLE void doStuff();
 };

backend.cpp:

 #include "backend.h"

 #include <QDebug>

 void Backend::doStuff()
 {
     qDebug() << "Did stuff!";
 }

You can then call that function from any QML file:

 import QtQuick.Controls

 import MyModule

 ApplicationWindow {
     width: 400
     height: 400
     title: qsTr("C++ Button example")

     Button {
         text: qsTr("Click me")
         onClicked: Backend.doStuff()
     }
 }

If the C++ type only needs to be available to a small set of QML files, consider using QML_ELEMENT. For more ways of exposing C++ types to QML, see Choosing the Correct Integration Method Between C++ and QML.

This example assumes that the Backend type is available in a QML module. With CMake, this is done via qt_add_qml_module. For an example that demonstrates this in detail, see Building a QML application.

See which item has active focus

Write a property change signal handler for the window's activeFocusItem property:

 import QtQuick
 import QtQuick.Controls

 ApplicationWindow {
     width: 400
     height: 400
     visible: true
     title: qsTr("Active focus debugging example")

     onActiveFocusItemChanged: print("activeFocusItem: " + activeFocusItem)

     Row {
         TextField {
             objectName: "textField1"
         }
         TextField {
             objectName: "textField2"
         }
     }
 }

This will print the item which currently has active focus to the console. To ensure that the output is useful, give each item a descriptive objectName.

Create a time picker like Android's TimePickerDialog

We've prepared an example that consists of a few QML files which demonstrate how to do this. They can be used in your application in the following manner:

 import QtQuick
 import QtQuick.Layouts
 import QtQuick.Controls.Material

 ApplicationWindow {
     id: window
     width: 600
     height: 600
     visible: true
     title: qsTr("Time Picker Example")

     Material.theme: darkThemeSwitch.checked ? Material.Dark : Material.Light

     // Shows the selected time and opens the dialog.
     TimeComponentLabel {
         id: openDialogLabel
         width: parent.width - 80
         anchors.centerIn: parent
         font.pixelSize: Qt.application.font.pixelSize * 8
         renderTypeQuality: Text.VeryHighRenderTypeQuality
         interactive: !timePickerDialog.opened

         text: Qt.formatTime(new Date(1970, 1, 1, timePickerDialog.hours, timePickerDialog.minutes), "hh:mm")

         onTapped: timePickerDialog.openWithMode(TimePicker.Mode.Hours)
     }

     ColumnLayout {
         // We always want the openDialogLabel to be centered in the window, not us.
         // For that reason, we use anchors rather than putting the root items into a ColumnLayout.
         anchors.horizontalCenter: parent.horizontalCenter
         anchors.top: openDialogLabel.bottom
         anchors.topMargin: 24
         spacing: 12

         Switch {
             id: is24HourSwitch
             text: qsTr("24 Hour")
             checked: timePickerDialog.is24Hour
         }
         Switch {
             id: darkThemeSwitch
             text: qsTr("Dark")
         }
     }

     TimePickerDialog {
         id: timePickerDialog
         anchors.centerIn: parent
         is24Hour: is24HourSwitch.checked

         onTimeAccepted: print("A time was chosen - do something here!")
     }
 }

TimePickerDialog in its light theme.

TimePickerDialog in its dark theme.

Use a C++ enum in JavaScript

To expose a C++ enum to JavaScript (that is, QJSEngine, not QQmlEngine or QQmlApplicationEngine), use QJSEngine::newQMetaObject():

     QJSEngine engine;
     engine.installExtensions(QJSEngine::AllExtensions);

     QJSValue backendJsMetaObject = engine.newQMetaObject(&Backend::staticMetaObject);
     engine.globalObject().setProperty("Backend", backendJsMetaObject);

     Backend backend(&engine);
     const bool loaded = backend.load();

The enum can then be used from JavaScript:

 export function backendStatusUpdate(backendStatus) {
     if (backendStatus === Backend.Error) {
         console.warn("Error!")
         return
     }

     console.log("Backend loaded successfully")
 }

When using QQmlEngine or QQmlApplicationEngine, there are easier options; see Choosing the Correct Integration Method Between C++ and QML for more information.

backend.h:

 #include <QObject>
 #include <QJSEngine>

 class Backend : public QObject
 {
     Q_OBJECT

 public:
     Backend(QJSEngine *engine);

     enum Status {
         Unknown,
         Error,
         Loading,
         Loaded
     };

     Q_ENUM(Status)

     bool load();

 private:
     QJSEngine *mEngine = nullptr;
 };

backend.cpp:

 #include "backend.h"

 Backend::Backend(QJSEngine *engine) :
     mEngine(engine)
 {
 }

 bool Backend::load()
 {
     // Do some loading here...

     const QJSValue module = mEngine->importModule(":/script.mjs");
     if (module.isError()) {
         qWarning() << "Error loading script.mjs:" << module.toString();
         return false;
     }

     const QJSValue function = module.property("backendStatusUpdate");
     if (!function.isCallable()) {
         qWarning() << "backendStatusUpdate script function is not callable!";
         return false;
     }

     const QJSValue functionResult = function.call(QJSValueList() << Loaded);
     if (functionResult.isError()) {
         qWarning() << "backendStatusUpdate script function had errors:" << functionResult.toString();
         return false;
     }

     return true;
 }

For more information, see QObject Integration.