找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

QML经验谈(一)QML和C++的相互调用

yafeilinux 2013-12-19 13:13 10084人围观 yafeilinux原创

该文章原创于Qter开源社区(www.qter.org),作者Joey_Chan,转载请注明出处!可以到这里讨论该文章。

QML经验谈(一)

该系列教程主要讲授有关QML的实用经验,不建议完全没有Qt经验的童鞋阅读(不包括熟悉Qt C++不懂QML的)

初学QML的童鞋,也许刚刚懂得怎么用一些基本element的用法和一些动画效果,或许童鞋们会发现,QML在功能上也有很多局限性,特别是许多QT C++的功能在QML上实现不了,这时,C++仍然显得十分重要,结合QML与C++就更重要了。

1.官方文档
在QT帮助文档里面,搜索“Exposing Attributes of C++ Types to QML”即可找到权威的内容,英文好的童鞋可以直接忽略我的教程看这个。

2.案例
下面以一个简单的Qt5模板程序为例子

新建一个QtQuick2应用程序,添加一个C++类,我这里叫Test类,继承QObject,然后修改test.h头文件如下:

  1. #ifndef TEST_H
  2. #define TEST_H

  3. #include
  4. #include

  5. class Test : public QObject
  6. {
  7.     Q_OBJECT
  8. public:
  9.     explicit Test(QObject *parent = 0);

  10. signals:

  11. public slots:
  12.     QString showString();  //这个是给QML调用的

  13. };

  14. #endif // TEST_H
复制代码
然后test.cpp的showString()函数如下:

  1. QString Test::showString()
  2. {
  3.     return "String from C++";
  4. }
复制代码
再修改main.cpp文件如下:

  1. #include
  2. #include   // 注意这里,没有这行会报错
  3. #include "qtquick2applicationviewer.h"
  4. #include "test.h"

  5. int main(int argc, char *argv[])
  6. {
  7.     QGuiApplication app(argc, argv);

  8.     Test *test = new Test(); // 刚刚新建的类

  9.     QtQuick2ApplicationViewer viewer;
  10.     viewer.engine()->rootContext()->setContextProperty("test", test);  // 将新的类映射为QML的一个对象
  11.     viewer.setMainQmlFile(QStringLiteral("qml/qmltest0/main.qml"));
  12.     viewer.showExpanded();

  13.     return app.exec();
  14. }
复制代码
现在回到main.qml文件,修改如下

  1. import QtQuick 2.0

  2. Rectangle {
  3.     width: 360
  4.     height: 360
  5.     Text {
  6.         id: title
  7.         text: qsTr("Hello World")
  8.         anchors.centerIn: parent
  9.     }
  10.     MouseArea {
  11.         anchors.fill: parent
  12.         onClicked: {
  13.             title.text = test.showString()  //将上面的标题改为前面c++写入的字符串
  14.         }
  15.     }
  16. }
复制代码
点“运行”,点一下界面就有效果了,懒得截图

3. 进阶
前面的例子示范了如果使用QML操控C++,但是反过来行不行呢? (不行的话我写出来干嘛)

来到test.h,修改如下:

  1. #ifndef TEST_H
  2. #define TEST_H

  3. #include
  4. #include

  5. class Test : public QObject
  6. {
  7.     Q_OBJECT
  8. public:
  9.     explicit Test(QObject *parent = 0);

  10. signals:
  11.     void callQml(QString msg);  // 这个信号是连接QML的关键,第一个字母必须小写

  12. public slots:
  13.     QString showString();
  14.     void callQmlSlot();  // 这个只是辅助发送信号的,非必要

  15. };

  16. #endif // TEST_H
复制代码
再来到test.cpp文件,修改如下:

  1. #include "test.h"

  2. Test::Test(QObject *parent) :
  3.     QObject(parent)
  4. {
  5.     QTimer::singleShot(3000, this, SLOT(callQmlSlot()));  // 用计时器来激活信号
  6. }

  7. QString Test::showString()
  8. {
  9.     return "String from C++";
  10. }

  11. void Test::callQmlSlot()
  12. {
  13.     emit this->callQml("call from C++"); // 计时器会启动这个槽函数,从而发送信号
  14. }
复制代码
最后就是main.qml了,修改如下

  1. import QtQuick 2.0

  2. Rectangle {
  3.     width: 360
  4.     height: 360
  5.     Text {
  6.         id: title
  7.         text: qsTr("Hello World")
  8.         anchors.centerIn: parent
  9.     }
  10.     MouseArea {
  11.         anchors.fill: parent
  12.         onClicked: {
  13.             title.text = test.showString()
  14.         }
  15.     }

  16.     Connections {  // 关键:Connections就是专门用来获取qml对象的信号的,这个test类已经被映射为qml对象了
  17.         target: test  // 目标对象

  18.         onCallQml: {  // 接收信号的名字,注意前面有个on,信号名第一个字母要大写
  19.             title.text = msg  // 更换标题
  20.         }
  21.     }
  22. }

复制代码
然后,点运行,效果会自动出来,我也懒得截图了  


7人点赞鲜花

1人点赞握手

雷人

1人点赞路过

鸡蛋

刚表态过的朋友 (9 人)

原作者: Joey_Chan

yafeilinux和他的朋友们微信公众号二维码

微信公众号

专注于Qt嵌入式Linux开发等。扫一扫立即关注。

Qt开源社区官方QQ群二维码

QQ交流群

欢迎加入QQ群大家庭,一起讨论学习!


公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了