迫于无奈开始写android的程序,以前使用QWidget的方式试过,虽然界面可以实现,但是最后调用摄像头时,未能成功,再没有继续。这几天开始使用qml进行尝试,在使用的过程中,其中的一个难点,就是在qml与c++中数据的交互。
我所使用的方式,是通过C++调用远端的webservice,再次数据送到qml端,不说原理了,直接上代码的实现过程。需要明白一点:qml不接受QList的类方式,所以使用了QList<QObject*>。大致分为四步,按需要看:
一、定义可交互的类,可以IDE生成中选择基类为QObject完成即可,基本代码自动生成。
h:
#ifndef TEST_H
#define TEST_H
#include <QObject>
class test : public QObject
{
Q_OBJECT
public:
explicit test(QObject *parent = nullptr);
signals:
public slots:
};
#endif // TEST_H
cpp:
#include "test.h"
test::test(QObject *parent) : QObject(parent)
{
}
以上文件中,最重要的两点:继承自QObject以及包含Q_OBJECT均完成。
定义属性时,需要写在Q_OBJECT下面,没有分号,可以使用快捷键对相关的代码进行自动生成,演示一个字段属性,完成后的代码如下,字段名为name:
#ifndef TEST_H
#define TEST_H
#include <QObject>
class test : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
public:
explicit test(QObject *parent = nullptr);
QString name() const
{
return m_name;
}
signals:
public slots:
void setName(QString name)
{
m_name = name;
}
private:
QString m_name;
};
#endif // TEST_H
在自动生成数据时,最好先写入一个private节,这个自动生成的时候没有,定义后,使用的私有变量会放在这里,否则会跟在public slots下,反正是最下面了。
二、数据操作类
数据操作类的生成方法与上步类似,不同的是需要定义操作的方法,以返回数据的为数据集为例,在public中定义一个方法,类名定义为c_test:
Q_INVOKABLE QList<QObject*> getData() const;
如果返回的只是一个单值,则这样:
Q_INVOKABLE QString getData() const;
赋值:
QList<QObject*> c_test::getData() const
{
QList<QObject*> r_list;
...
test *t1 = new test;
t1.setName("...");
r_list.append(t1);
...
return r_list;
}
三、注册
注册是指将C++的类注册到qml中供调用,貌似有两种方式,我使用的是setContextProperty。在main中,connect前:
engine.rootContext()->setContextProperty("c_test", new c_test);
经测试,在1中所定义的类,不需要注册。
四、qml调用
将值给ListMode时,需要进行一次迭代。
var data = c_test.getData()
_model.clear()
for(var i=0;i<data.length;i++){
_model.append(data[i]);
}
如上代码中的c_test.getData()就是使用注册的类进行的操作。
此处迭代是必须的,不能直接给model。
在qml中显示:
Text{
text: name
}
这里所使用的name,就是在一的类里所定义的属性。
这个一直做为拦路虎的东西,在实现后发现也并不是很麻烦。以上方式测试通过,熟练了一种之后,如果需要可以再看其它,应该就简单了吧。