找回密码
 立即注册
收起左侧

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

37
回复
29281
查看
[复制链接]

尚未签到

来源: 2013-12-19 23:03:27 显示全部楼层 |阅读模式

马上注册,查看详细内容!注册请先查看:注册须知

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
该文章原创于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 <QObject>
  4. #include <QtCore>

  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 <QtGui/QGuiApplication>
  2. #include <QtQuick>  // 注意这里,没有这行会报错
  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 <QObject>
  4. #include <QtCore>

  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. }

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

参与人数 2人气 +4 收起 理由
西洛 + 1 很详细!
xflcx1991 + 3 很实用!

查看全部评分总评分 : 人气 +4

回复

使用道具 举报

累计签到:1564 天
连续签到:1 天
2013-12-20 09:58:38 显示全部楼层
呵呵,终于开始将qml的内容了!建议把标题改下:比如QML经验谈(一)QML和C++的相互调用
这样让网友一眼明白文章的主要内容。
回复 支持 反对

使用道具 举报

尚未签到

2013-12-20 10:15:06 显示全部楼层
yafeilinux 发表于 2013-12-20 09:58
呵呵,终于开始将qml的内容了!建议把标题改下:比如QML经验谈(一)QML和C++的相互调用
这样让网友一眼明 ...

这就改
回复 支持 反对

使用道具 举报

累计签到:114 天
连续签到:1 天
2013-12-20 20:29:56 显示全部楼层
支持                                                                                                            
回复 支持 反对

使用道具 举报

累计签到:17 天
连续签到:1 天
2013-12-21 22:13:25 显示全部楼层
嗯,受用了。谢谢楼主的文章。
回复 支持 反对

使用道具 举报

累计签到:196 天
连续签到:1 天
2013-12-28 22:50:48 显示全部楼层
希望完整些!                                                           
回复 支持 反对

使用道具 举报

累计签到:16 天
连续签到:1 天
2014-1-6 11:16:48 显示全部楼层
学习了,太好了,赞一个!
回复 支持 反对

使用道具 举报

累计签到:5 天
连续签到:1 天
2014-2-28 21:35:21 显示全部楼层
我想了解在Qt Qlabel里的图片怎么转到Qml去呢?
回复 支持 反对

使用道具 举报

尚未签到

2014-3-5 14:52:04 显示全部楼层
楼主继续啊,期望看到二。。。。。。。。
回复 支持 反对

使用道具 举报

尚未签到

2014-3-5 15:18:41 显示全部楼层
xxqt 发表于 2014-3-5 14:52
楼主继续啊,期望看到二。。。。。。。。

最近挺忙的,估计要排期到3月底。。。
回复 支持 反对

使用道具 举报

尚未签到

2014-3-6 10:28:07 显示全部楼层
Joey_Chan 发表于 2014-3-5 15:18
最近挺忙的,估计要排期到3月底。。。

楼主辛苦。。。。已经是三月了,很期待楼主的大作
回复 支持 反对

使用道具 举报

尚未签到

2014-3-12 13:43:42 显示全部楼层
如何把串口读到的数据传给qml界面,能指教下吗
回复 支持 反对

使用道具 举报

尚未签到

2014-3-12 17:59:07 显示全部楼层
xxqt 发表于 2014-3-12 13:43
如何把串口读到的数据传给qml界面,能指教下吗

只要是非二进制的数据都能用我这方法传

你把读到的数据放进信号里面就行了
回复 支持 反对

使用道具 举报

尚未签到

2014-3-13 10:44:13 显示全部楼层
Joey_Chan 发表于 2014-3-12 17:59
只要是非二进制的数据都能用我这方法传

你把读到的数据放进信号里面就行了 ...

com.h
#ifndef COM_H
#define COM_H

#include <QtSerialPort/QSerialPort>#include <QtSerialPort/QSerialPortInfo>
#include <QObject>#include <QtCore>

class mycom : public QObject{    Q_OBJECT
public:    mycom(QObject *parent = 0);    ~mycom();        QSerialPort *MyScom;    QString temp; signals: public slots:    QString readmycom();};
#endif // COM_H
com。cpp
#include "com.h"
mycom::mycom(QObject *parent)    : QObject(parent){       MyScom=new QSerialPort(this);    MyScom->setPortName("com1");
    MyScom->open(QIODevice::ReadWrite);    MyScom->setBaudRate(QSerialPort::Baud9600);
    MyScom->setDataBits(QSerialPort::Data8);    MyScom->setStopBits(QSerialPort::OneStop);    MyScom->setParity(QSerialPort::NoParity);    MyScom->setFlowControl(QSerialPort::NoFlowControl);    connect(MyScom,SIGNAL(readyRead()),this,SLOT(readmycom()));   
}
mycom::~mycom(){}
QString mycom::readmycom(){     temp=MyScom->readAll().toHex();   return temp;
}
main。cpp
#include <QtGui/QGuiApplication>#include <QtQuick>
#include "qtquick2applicationviewer.h"#include "test.h"#include"com.h"int main(int argc, char *argv[]){    QGuiApplication app(argc, argv);      mycom *mycom1= new mycom();    QtQuick2ApplicationViewer viewer;    viewer.setMainQmlFile(QStringLiteral("qml/qmlc/main.qml"));
   viewer.engine()->rootContext()->setContextProperty("mycom1", mycom1);    viewer.showExpanded();
    return app.exec();}
main。qml
import QtQuick 2.0
Rectangle {    width: 360    height: 360    Text {        id: title        text: qsTr("Hello World")                anchors.centerIn: parent    }    MouseArea {        anchors.fill: parent        onClicked: {                     
             title.text=mycom1.readmycom()        }    }}
回复 支持 反对

使用道具 举报

尚未签到

2014-3-13 10:44:57 显示全部楼层
一个回复里不让写那么多字

我是在你的程序上修改的,你的程序没问题,我的那个读串口的程序也通过测试了,麻烦你帮我看下问题出在哪?
回复 支持 反对

使用道具 举报

尚未签到

2014-3-13 10:46:47 显示全部楼层
这个代码贴上去怎么就有些乱
回复 支持 反对

使用道具 举报

尚未签到

2014-3-13 14:44:11 显示全部楼层
xxqt 发表于 2014-3-13 10:44
一个回复里不让写那么多字

我是在你的程序上修改的,你的程序没问题,我的那个读串口的程序也通过测试了, ...

你光贴代码我怎么看。。。你不如把程序的算法跟我描述一下更好

绝大多数时候,只要算法没问题,代码出错都很容易改,反之你懂的
回复 支持 反对

使用道具 举报

尚未签到

2014-3-13 14:53:43 显示全部楼层
Joey_Chan 发表于 2014-3-13 14:44
你光贴代码我怎么看。。。你不如把程序的算法跟我描述一下更好

绝大多数时候,只要算法没问题,代码出错 ...

代码是在你的基础上改的。新建一个串口类,然后把这个类映射到qml里,在qml中点击鼠标的时候,界面上的值由helloworld变为当前的串口值。
回复 支持 反对

使用道具 举报

尚未签到

2014-3-13 17:55:44 显示全部楼层
xxqt 发表于 2014-3-13 14:53
代码是在你的基础上改的。新建一个串口类,然后把这个类映射到qml里,在qml中点击鼠标的时候,界面上的值 ...

如果是这样的话,鼠标点击后触发你的串口类的public slot函数,然后你这个函数用信号把这个串口的值传出来,在qml里面用connection接收

这里要注意我这种方法不支持传二进制数据
回复 支持 反对

使用道具 举报

尚未签到

2014-3-14 09:33:38 显示全部楼层
Joey_Chan 发表于 2014-3-13 17:55
如果是这样的话,鼠标点击后触发你的串口类的public slot函数,然后你这个函数用信号把这个串口的值传出 ...

我现在改了下,当串口读到数据就发射一个信号,通知qml显示数据,发射信号是这样的:QString mycom::readmycom()
{
     emit dataComing();

}
然后在qml里显示数据是这样的:Connections
    {
        target: mycom1
        onDataComing:title.text=mycom1.displayShit()
    }

displayShit()是这样的:QString mycom::displayShit()
{
    temp=MyScom->readAll().toHex();
  return temp;
}

这样后 开发板一上电就报错
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

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