如何在QML中调用C++的方法并接收C++的信号

本文介绍如何在QML中调用C++方法并接收C++信号。通过示例展示如何定义C++类中的Q_INVOKABLE方法及信号,并在QML文件中触发这些方法及响应信号。

如何在QML中调用C++的方法并接收C++的信号

在QML中调用c++方法并接收信号

继续上一篇的内容使用C++创建新的QML类型,接下来我们在PieChart 这个类中添加一个函数"clearChart()" 和一个信号"chartCleared",这样在app.qml中就可以像下面一样调用这个函数,并接收这个信号了:

import Charts 1.0
import QtQuick 1.0
 
 Item {
     width: 300; height: 200
 
     PieChart {
         id: aPieChart
         anchors.centerIn: parent
         width: 100; height: 100
         color: "red"
 
         onChartCleared: console.log("The chart has been cleared")
     }
 
     MouseArea {
         anchors.fill: parent
         onClicked: aPieChart.clearChart()
     }
 
     Text {
         anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
         text: "Click anywhere to clear the chart"
     }
 }

SimpleChart2.png

为c++类添加被调用的方法和信号

下面我们就来看一下在C++的类中我们具体应该怎么做:

class PieChart : public QDeclarativeItem
 {
     ...
 public:
     ...
     Q_INVOKABLE void clearChart();
 
 signals:
     void chartCleared();
     ...
 };

使用Q_INVOKABLE 使得Qt Meta-Object 系统可以访问到clearChart() 方法,于是QML也可以访问到这个方法了。请注意,由于槽函数(slots)也可以被QML调用,因此clearChart() 也可以被声明为一个Qt slot 而不使用Q_INVOKABLE。这两种方式都是有效的。

clearChart() 方法将绘制扇形图的画笔颜色设置成Qt::transparent(透明),并重绘扇形图,最后发出chartCleared()信号:

void PieChart::clearChart()
 {
     setColor(QColor(Qt::transparent));
     update();
 
     emit chartCleared();
 }


运行程序

现在我们可以启动这个应用程序并点击其窗口区域,于是窗口上的扇形图就消失了,并且应用程序有如下输出:

The chart has been cleared

大家可以在 Qt 的 examples/declarative/tutorials/extending/chapter2-methods目录中找到这个程序的完整代码。


相关链接

### 从 QML 调用 C++ 函数的方法 在 Qt 开发中,QMLC++ 的交互是一个常见的需求。可以通过以下几种方式从 QML 调用 C++ 函数: #### 1. 使用 `qmlRegisterType` 注册自定义类型 这种方法允许将 C++ 类型注册为 QML 可用的类型,通过 QML 调用该类型的函数。 ```cpp class MyCppClass : public QObject { Q_OBJECT public: explicit MyCppClass(QObject *parent = nullptr) : QObject(parent) {} Q_INVOKABLE QString greet() const { return "Hello from C++!"; } }; ``` 注册该类型QML 中使用: ```cpp qmlRegisterType<MyCppClass>("com.example", 1, 0, "MyCppClass"); ``` QML 文件中调用: ```qml import com.example 1.0 Item { MyCppClass { id: cppObj } Text { text: cppObj.greet() } } ``` #### 2. 使用 `setContextProperty` 传递 C++ 对象 将一个 C++ 对象作为上下文属性传递到 QML 上下文中,QML 可以直接访问该对象的属性和函数。 ```cpp MyCppClass cppObj; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("cppObj", &cppObj); ``` QML 文件中调用: ```qml Text { text: cppObj.greet() } ``` #### 3. 使用 `QMetaObject::invokeMethod` 调用 QML 函数 如果需要从 C++ 调用 QML 中定义的函数,可以使用 `QMetaObject::invokeMethod` 方法。 ```cpp QVariant res; QVariant argName = "John"; QVariant argAge = 25; bool flag = QMetaObject::invokeMethod(windowObj, "qmlFuncObj", Q_RETURN_ARG(QVariant, res), Q_ARG(QVariant, argName), Q_ARG(QVariant, argAge)); qDebug() << "res = " << res; ``` QML 文件中定义函数: ```qml function qmlFuncObj(name, age) { return "Received: " + name + ", Age: " + age; } ``` #### 4. 使用 `Q_PROPERTY` 暴露属性 对于需要与 QML 交互的属性,可以使用 `Q_PROPERTY` 宏定义属性,通过 QML 访问和修改。 ```cpp class MyCppClass : public QObject { Q_OBJECT Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged) public: int getValue() const { return m_value; } void setValue(int value) { if (m_value != value) { m_value = value; emit valueChanged(); } } signals: void valueChanged(); private: int m_value = 0; }; ``` QML 文件中访问属性: ```qml Text { text: "Value: " + cppObj.value } ``` ### 示例代码总结 以下是完整的 C++QML 示例代码: C++ 部分: ```cpp #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include <QMetaObject> class MyCppClass : public QObject { Q_OBJECT Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged) public: explicit MyCppClass(QObject *parent = nullptr) : QObject(parent), m_value(0) {} int getValue() const { return m_value; } void setValue(int value) { if (m_value != value) { m_value = value; emit valueChanged(); } } Q_INVOKABLE QString greet() const { return "Hello from C++!"; } signals: void valueChanged(); private: int m_value; }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); MyCppClass cppObj; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("cppObj", &cppObj); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } #include "main.moc" ``` QML 部分: ```qml import QtQuick 2.15 import QtQuick.Window 2.15 Window { width: 400 height: 300 visible: true title: "QML and C++ Interaction" Text { text: "Value: " + cppObj.value } Button { text: "Increment Value" onClicked: { cppObj.value += 1 } } Text { text: cppObj.greet() } } ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值