Qt Quick 快捷指南

本页面旨在提供一个易于查找、有用的参考,展示在 Qt Quick 中执行特定任务的最简单和最佳方式。每个解决方案提供了 QML 和/或 C++ 代码片段(如有适用),并且每个片段都经过 Qt 自动测试以确保其可用性。

如何

当按钮被点击时从 QML 中调用 C++ 函数

假设 C++ 类型必须对应用程序中的 QML 文件全局可用,最简单的方式是将其作为一个带有 QML_SINGLETON 的 QML 单例。例如,在头文件中,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!";
}

然后您可以从任何 QML 文件中调用该函数

import QtQuick.Controls

import MyModule

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

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

如果 C++ 类型仅需对一组小的 QML 文件可用,考虑使用 QML_ELEMENT。有关将 C++ 类型公开给 QML 的更多方式,请参阅 选择 C++ 和 QML 之间正确集成方法

此示例假设 Backend 类型在一个 QML 模块中可用。使用 CMake,这是通过 qt_add_qml_module 实现的。有关详细介绍此的示例,请参阅 构建 QML 应用程序

查看哪个项目有活动焦点

为窗口的 activeFocusItem 属性编写一个 属性变更信号处理器

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"
        }
    }
}

这将打印当前具有活动焦点的项目到控制台。为了确保输出的实用性,请给每个项目一个有描述性的 objectName

创建类似 Android 的 TimePickerDialog 的时间选择器

我们已经准备了一个示例,它包含几个 QML 文件,这些文件演示了如何做到这一点。它们可以用以下方式在你的应用程序中使用

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 在其浅色主题中。

TimePickerDialog 在其深色主题中。

在 JavaScript 中使用 C++ 枚举

要公开 C++ 枚举到 JavaScript(即,QJSEngine,而非 QQmlEngineQQmlApplicationEngine),请使用 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();

然后可以从 JavaScript 中使用该枚举

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

    console.log("Backend loaded successfully")
}

在使用QQmlEngineQQmlApplicationEngine时,有更简便的选项;更多详细信息,请参阅C++和QML之间选择正确集成方法

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;
}

有关更多信息,请参阅QObject 集成

© 2024 Qt公司有限公司。本文档中的文档贡献为各自拥有者的版权。本提供的文档受GNU自由文档许可证版本1.3的条款许可,由自由软件基金会发布。Qt及其相关标志是Qt公司在芬兰和/或其他国家的商标。所有其他商标均为其各自拥有者的财产。