第四章:QML中呼叫C++互動
1、QML中呼叫C++互動方法
Qt整合了QML引擎和Qt元物件系統,使得QML很容易從C++中得到擴充套件,在一定的條件下,QML就可以訪問QObject派生類的成員,例如訊號、槽函式、列舉型別、屬性、成員函式等。
QML訪問C++需要將c++類擴充套件到qml中,有兩個方法:
1、在Qt元物件系統中註冊C++類到qml中
2、將物件或資料暴露給 QML
相關函式:
setContextProperty()//將物件或資料暴露給 QML
qmlRegisterType()//註冊C++類到qml中
qmlRegisterSingletonType()//註冊C++單例到qml中
實現可以被QML訪問的C++類的屬性和方法 必須滿足兩個條件:
1、派生自QObject類或QObject類的子類
2、使用Q_OBJECT巨集
訪問屬性和方法:
1、訊號與槽 可以直接訪問
2、列舉型別 使用Q_ENUMS()巨集
3、屬性 使用Q_PROPERTY()巨集
4、方法 使用Q_INVOKABLE()巨集
2、Q_PROPERTY巨集
作用:
用來定義可通過元物件系統訪問的屬性,通過它定義的屬性,可以在 QML 中訪問、修改,也可以在屬性變化時發射特定的訊號。該巨集是qt特有的,必須繼承於QObject類。
寫法:
Q_PROPERTY(type name # 屬性
READ getFunction # 讀取屬性值,必須返回屬性的型別的值或指標或引用
[WRITE setFunction] # 設定屬性值,返回空並且至少具有一個引數
[RESET resetFunction] # 設定屬性的值到預設值
[NOTIFY notifySignal] # 屬性的值發生改變時發出訊號
[DESIGNABLE bool] # 此屬性是否在介面設計器的屬性編輯器中出現
[SCRIPTABLE bool] # 屬性是否可以被一個指令碼引擎操作
[STORED bool] # 屬性是否被認為是獨立存在還是依賴於其它的值而存在
[USER bool] # 屬性是否被設計為面向使用者的或使用者可修改的類屬性
[CONSTANT] # 屬性的值是不變的
[FINAL]) # 屬性不能被派生類所重寫
訊號命名:
將 NOTIFY 訊號命名為 <property>Changed 的形式,其中 <property> 是屬性的名稱。由 QML 引擎生成的關聯的屬性更改訊號處理程式將始終採用on<Property>Changed 的形式,而無需關心相關 C++ 訊號的名稱,因此建議訊號名稱遵循此約定,以避免任何混淆。
示例:
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QColor barColor READ getBarColor WRITE setBarColor)
3、Q_INVOKABLE巨集
作用:被修飾的成員函式能夠被元物件系統所喚起
QML 可以訪問 QObject 派生類的函式,但是函式需要滿足以下條件之一:
1、使用 Q_INVOKABLE() 巨集標記的 public 函式
2、public 槽函式
示例:
Q_INVOKABLE void qDebug_Info(int type, QString strInfo);
qmlRegisterType
作用:將C++實現的類在QML中呼叫的,連線C++和QML的一個工具
寫法:
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)
示例:
main.cpp
#include <QtQml>
qmlRegisterType<Boy>("People", 1,0, "Boy");
qmlRegisterType<Girl>("People", 1,0, "Girl");
xxx.qml
import People 1.0
Boy{
id:boy
...
}
Girl{
id:girl
...
}
4、setContextProperty
作用:將物件或資料暴露給 QML,一般預設就是全域性單例
示例:QML中使用C++日誌記錄模組
qmllog4qml.h
#include <QObject>
class QmlLog4Qml : public QObject
{
Q_OBJECT
public:
QmlLog4Qml();
Q_INVOKABLE void qDebug_Info(int type, QString strInfo);
};
qmllog4qml.h.cpp
#include "qmllog4qml.h"
#include <QMutex>
#include <QFile>
#include <QDateTime>
#include <QTextStream>
void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
static QMutex mutex;
mutex.lock();
QString text;
switch(type)
{
case QtDebugMsg:
text = QString("Debug:");
break;
case QtWarningMsg:
text = QString("Warning:");
break;
case QtCriticalMsg:
text = QString("Critical:");
break;
case QtFatalMsg:
text = QString("Fatal:");
}
QString message = "";
if (context.file != nullptr)
{
QString context_info = QString("File:(%1) Line:(%2)").arg(QString(context.file)).arg(context.line);
QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
QString current_date = QString("(%1)").arg(current_date_time);
message = QString("%1 %2 %3 %4").arg(current_date).arg(text).arg(context_info).arg(msg);
}
else
{
message = msg;
}
QFile file("log.txt");
file.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream text_stream(&file);
text_stream << message << "\r\n";
file.flush();
file.close();
mutex.unlock();
}
QmlLog4Qml::QmlLog4Qml()
{
qInstallMessageHandler(outputMessage);
}
void QmlLog4Qml::qDebug_Info(int type, QString strInfo)
{
QMessageLogContext context;
context.file = nullptr;
outputMessage((QtMsgType)type, context, strInfo);
}
main.cpp
設定上下文屬性:setContextProperty() 匯出屬性,就可以在 QML 中使用了
#include "qmllog4qml.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QmlLog4Qml log4Qml;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("log4Qml", &log4Qml);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
QML: 不需要 import 語句,可以直接呼叫 log4Qml.qDebug_Info()
...
Page1Form {
Keys.enabled: true
Keys.onEscapePressed: {
Qt.quit()
}
searchbutton.onClicked: {
log4Qml.qDebug_Info(0, "Qml寫日誌"); //呼叫C++介面
console.log("查詢內容:" + searchTextField.text);
}
...
}
相關文章
- (譯)通過WebChannel/WebSockets與QML中的HTML互動WebHTML
- QT QML模組與C++的互動QTC++
- 29.qt quick-在QML中呼叫C++類QTUIC++
- C++ addon
- C++ 與 QML 之間進行資料互動的幾種方法C++
- QMl 中alias 的基本用法
- PixiJS原始碼分析系列:第四章 響應 Pointer 互動事件(上篇)JS原始碼事件
- 【qml】❤
- PHP如何呼叫實現奇亞(Chia)互動[支援XCH]PHP
- QML::qml與c++混編C++
- 在 C/C++ 中使用 TensorFlow 預訓練好的模型—— 直接呼叫 C++ 介面實現C++模型
- 前後端資料互動(三)——ajax 封裝及呼叫後端封裝
- QML::ListViewView
- QML Document
- Qml 實現水波進度動畫條動畫
- javascript忍者祕籍-第四章 理解函式呼叫JavaScript函式
- 與 AI 互動 - 學習如何看呼叫鏈堆疊資訊AI
- PHP 如何呼叫實現波場互動[支援TRX/TRC20]PHP
- PHP 如何通過 JSON-RPC 呼叫實現以太坊互動PHPJSONRPC
- PHP 如何透過 JSON-RPC 呼叫實現以太坊互動PHPJSONRPC
- 互動視訊不能為了互動而互動
- 05 . Vue前端互動,fetch,axios,以asyncawait方式呼叫介面使用及案例Vue前端iOSAI
- Java與WCF互動(一):Java客戶端呼叫WCF服務 (轉)Java客戶端
- C++程式碼閱讀筆記(一)筆記
- swoole phpy PHP 與 Python 互呼叫庫PHPPython
- iOS中WKWebView互動使用總結iOSWebView
- golang呼叫模組程式實現互動輸入自動化,獲取imei及iccidGolang
- VS中呼叫DLL動態庫的方法
- 在Qml 中定義訊號並如何觸發
- 學習 HT for Web 中的互動事件Web事件
- 互動媒體日常——互動漫畫之對話方塊互動
- Python|Python互動之mongoDB互動詳解PythonMongoDB
- qml釋出專案
- qml基礎知識
- qml 滑塊Slider RangeSliderIDE
- Python中動態類和動態方法的建立與呼叫Python
- 淺談遊戲中的互動敘事遊戲
- 如何在Unity中實現水體互動?Unity