QML 怎麼調用 C++ 中的內容?

以下內容為本人的學習筆記,如需要轉載,請聲明原文鏈接 微信公眾號「englyf」//mp.weixin.qq.com/s/z_JlmNe6cYldNf11Oad_JQ


先說明一下測試環境

編譯器:vs2017x64

開發環境:Qt5.12

這裡主要是總結一下,怎麼在 QML 文件中引用 C ++ 文件里定義的內容?

很簡單,我們可以在 C ++ 文件中通過 QML 引擎(QQmlEngine class)的上下文對象(QQmlContext)調用方法 setContextProperty 設置對應的引用即可。詳情看看下面的方法聲明:

void QQmlContext::setContextProperty(const QString &name, QObject *value);
void QQmlContext::setContextProperty(const QString &name, const QVariant &value);

可以看到,既可以設置 QObject 類型的對象(指針),也可以設置 QVariant 兼容的類型數據(包括基本類型數據等)到 QML 引擎的上下文中。然後在 QML 中就可以通過引用名 name 直接調用即可。

1. 設置類型數據

// main.cpp
#include <QDateTime>
void main() {
    //...
    QQmlEngine engine;
    QDateTime dateTime = QDateTime::currentDateTime();
    engine.rootContext()->setContextProperty("dateTime", &dateTime);
    //...
}

以上程式碼中直接將 QDateTime 類型的數據設置到引擎上下文中。

Rectangle {
    id: window
    //...
    Text {
      text: dateTime
    }
}

通過引用名 dateTime 將 C ++ 文件中的數據綁定到組件 Text 的 text 屬性上,進而顯示出來。

2. 設置對象指針

上面是設置數據,這裡設置的是 QObject 類型的指針,所以在 QML 里還可以調用 C ++ 文件中定義的對象,包括屬性和方法等。

首先,定義一個 QObject 的派生類 ApplicationData,從 QObject 派生是必須的。

// applicationdata.h
#include <QObject>
#include <QDateTime>
#include <QTimer>

class ApplicationData : public QObject
{
    Q_OBJECT

public:
    ApplicationData(){
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, &ApplicationData::slt_timeout);
        timer->start(1000);
    }

    Q_INVOKABLE QDateTime getCurrentDateTime() const {
        return m_currentDateTime;
    }

signals:
    void sig_dataTimeUpdated();

private slots:
    void slt_timeout() {
        m_currentDateTime = QDateTime::currentDateTime();
        emit sig_dataTimeUpdated();
    }

private:
    QDateTime m_currentDateTime;
};

其中 Q_INVOKABLE 用於聲明此方法可被元對象系統調用。這個類實現每 1000 ms 刷新內部日期時間屬性,並且發射訊號 sig_dataTimeUpdated,此屬性值可以通過調用定義的公共方法 getCurrentDateTime() 得到。

下面再來定義程式入口文件:

// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "applicationdata.h"

int main(int argc, char *argv[])
{
    qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    ApplicationData data;
    engine.rootContext()->setContextProperty("currentDateTime", &data);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

在 QML 引擎裝載 QML 文件前,先將類 ApplicationData 的對象指針設置到上下文中。

下面再看看怎麼調用指針對應的類對象。

// main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.VirtualKeyboard 2.4

Window {
    id: window
    visible: true
    title: qsTr("Hello World")

    Text {
        id: name_id
        anchors.centerIn: parent
    }

    Connections {
        target: currentDateTime
        onSig_dataTimeUpdated: {
            name_id.text = currentDateTime.getCurrentDateTime();
        }
    }
}

使用 Connections 連接數據對象 currentDateTime 的訊號,當指針對象的訊號 sig_dataTimeUpdated 發射出來時,調用方法 getCurrentDateTime() 並用結果設置組件 Text 的屬性 text。
顯示的效果是動態刷新時間日期數據的,這和在上下文中設置類型數據不同(不會刷新),如下圖:

其實在我的另一篇博文《一文入門Qt Quick》中也有對這一塊主題的說明,不妨去看看吧!


Tags: