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
- See which item has active focus
- Create a time picker like Android's TimePickerDialog
- Use a C++ enum in JavaScript
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.
© 2024 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.