Qt中如何註冊一個C++類到qml

作者:billy
版權聲明:著作權歸作者所有,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處

前言

在進行 Qt Quick 開發時, 有些需求是無法在 QML 中實現的,我們必須要使用C++中的方法來完成它,這個時候我們就需要實現 QML 與 C++ 的混合編程

通常我們會先把需要的功能在 C++ 中全部完成,然後在 QML 中直接調用 C++ 中的方法。博主查看了Qt的幫助文檔發現一共有兩種方法可以實現。

方法一:在QML系統中註冊C++類型

官方文檔說明:
在這裏插入圖片描述具體步驟如下:

  1. 實現C++類的功能
myconfiguration.h

#ifndef MYCONFIGURATION_H
#define MYCONFIGURATION_H

#include <QObject>
#include <QSettings>

class MyConfiguration : public QObject
{
    Q_OBJECT
public:
    explicit MyConfiguration(QObject *parent = nullptr);

    // 使用 Q_INVOKABLE 宏修飾的方法纔可以在 QML 中被調用	
    Q_INVOKABLE void setProperty(QString name, QString section, QString key, QString value);

    Q_INVOKABLE QString getProperty(QString name, QString section, QString key);

signals:

public slots:
};

#endif // MYCONFIGURATION_H
myconfiguration.cpp

#include "myconfiguration.h"

MyConfiguration::MyConfiguration(QObject *parent) : QObject(parent)
{

}

void MyConfiguration::setProperty(QString name, QString section, QString key, QString value)
{
    QString fileName = name;
    QString path = section + "/" + key;

    QSettings *settings = new QSettings(fileName, QSettings::IniFormat);
    settings->setValue(path, value);
}

QString MyConfiguration::getProperty(QString name, QString section, QString key)
{
    QString fileName = name;
    QString path = section + "/" + key;

    QSettings *settings = new QSettings(fileName, QSettings::IniFormat);
    return settings->value(path, "").toString();
}
  1. 使用 qmlRegisterType 函數將類註冊到 QML 中
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "myconfiguration.h"
#include <QQmlContext>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    //參數:qmlRegisterType<C++類型名> (命名空間 主版本 次版本 QML中的類型名)
    qmlRegisterType<MyConfiguration, 1>("MyConfiguration", 1, 0, "MyConfiguration");

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}
  1. 使用 import 語句導入註冊時填寫的類所在的命名空間
  2. 在 QML 文件中實例化對象
  3. 通過該對象的 id 來訪問對象的屬性和方法
import QtQuick 2.12
import QtQuick.Window 2.12
// 導入命名空間
import MyConfiguration 1.0

Window {
    visible: true
    width: 640
    height: 480

    // 實例化對象
    MyConfiguration { id: myConfiguration }

    Rectangle {
        width: 200
        height: 160
        anchors.centerIn: parent
        color: "yellow"

        Text {
            id: myText
            anchors.centerIn: parent
            font.pixelSize: 24
            font.family: "微軟雅黑"
            color: "black"
            text: "測試"
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                // 通過 id 調用 getProperty 和 setProperty
                // 運行結果如下圖所示,獲取到配置文件中的 name 爲 billy 並賦值給 text
                // 修改配置文件中 age 的值爲 30
                myText.text  = myConfiguration.getProperty("config.ini", "base", "name")
                myConfiguration.setProperty("config.ini", "base", "age", "30")
            }
        }
    }
}

在這裏插入圖片描述
在這裏插入圖片描述

方法二:將對象設置爲上下文屬性

官方文檔說明:
在這裏插入圖片描述
在這裏插入圖片描述
具體步驟如下:

  1. 實現C++類的功能(同法一的第一步)
  2. 在 main.cpp 中完成屬性設置
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "myconfiguration.h"
#include <QQmlContext>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // 把類的實例化對象 myConfiguration 設置爲上下文屬性
    // 可以在所有qml文件中通過 applicationConfiguration 來調用該類的屬性和方法
    MyConfiguration myConfiguration;
    engine.rootContext()->setContextProperty("applicationConfiguration", &myConfiguration);

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}
  1. 在所有qml文件中都可以通過設置好的名字來調用該類中的屬性和方法;
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    visible: true
    width: 640
    height: 480

    Rectangle {
        width: 200
        height: 160
        anchors.centerIn: parent
        color: "yellow"

        Text {
            id: myText
            anchors.centerIn: parent
            font.pixelSize: 24
            font.family: "微軟雅黑"
            color: "black"
            text: "測試"
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                // 通過 applicationConfiguration 調用屬性和方法
                myText.text  = applicationConfiguration.getProperty("config.ini", "base", "name")
                applicationConfiguration.setProperty("config.ini", "base", "age", "30")
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章