作者:billy
版權聲明:著作權歸作者所有,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處
前言
在進行 Qt Quick 開發時, 有些需求是無法在 QML 中實現的,我們必須要使用C++中的方法來完成它,這個時候我們就需要實現 QML 與 C++ 的混合編程。
通常我們會先把需要的功能在 C++ 中全部完成,然後在 QML 中直接調用 C++ 中的方法。博主查看了Qt的幫助文檔發現一共有兩種方法可以實現。
方法一:在QML系統中註冊C++類型
官方文檔說明:
具體步驟如下:
- 實現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();
}
- 使用 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();
}
- 使用 import 語句導入註冊時填寫的類所在的命名空間;
- 在 QML 文件中實例化對象;
- 通過該對象的 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")
}
}
}
}
方法二:將對象設置爲上下文屬性
官方文檔說明:
具體步驟如下:
- 實現C++類的功能(同法一的第一步);
- 在 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();
}
- 在所有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")
}
}
}
}