背景:
【qml-4】qml与c++交互(类型多例)
之前提到的“实例注入”方式,是在c++中实例化再注入qml,手册中是不推荐这么做的。问AI答案是:
为什么避免context properties:
破坏组件封装性
使数据流难以追踪
导致组件难以单独测试
可能产生循环依赖
我认为有兴趣可以研究。
而之前提到的类型方式,用起来也不是我想要的“简洁”效果,实际项目中我用了一种自认为比较方便的用法,记录下来。
qml项目建议:
之前提到过qml分离方式我试出来并不好,于是使用qrc方式。我是从Design Studio里做好界面导出qrc,然后把qml目录和qrc复制到c++项目中使用的。
实际DS应该可以生成cmake,可以直接用creator原地打开项目,但它生成的东西太多,我就没有采用这种方式。
类型定义:
写个c++类,供qml使用。
//-----------------------cppdb.h------------------------------
#ifndef CPPDB_H
#define CPPDB_H
#include <QObject>
#include <QQmlEngine>
class CppDB : public QObject
{
Q_OBJECT
QML_ELEMENT
public:
explicit CppDB(QObject *parent = nullptr);
public:
//Logs
Q_INVOKABLE void f_Logs_Write(QString sLogText);
};
#endif // CPPDB_H
//-----------------------cppdb.cpp--------------------------
#include "cppdb.h"
CppDB::CppDB(QObject *parent)
: QObject{parent}
{}
/**
* Write the logs to db.
*/
void CppDB::f_Logs_Write(QString sLogText)
{
...
}
类型注册:
程序加载时调用即可,比如main函数中,应该放在qml load之前。我习惯是用另一个静态类写成静态函数,main函数中调用一行即可。以后方便维护。
qmlRegisterType<CppDB>("CppDB", 1, 0, "CppDB");
其中,第一个字符串用于qml中的import,第二个字符串用于qml中的类型引用(类似Button和Text)。然后就没有然后了,简单吧。
qml调用:
接着在qml中这样用:
import CppDB
Item {
CppDB { id: _cppDB }
function f() {
_cppDB.f_Logs_Write(qsTr("这条写入日志。举个例子而已。"));
}
}
总结:
上面就三步,不需要改qmakelists.txt,不需要涉及路径,我认为已经非常简练。
但要明白,这种用法跟自己写了个qml的Button一样,它就是个类型,qml中使用{}实例化它。亦即,如果这个类型在多个qml中使用,那就实例化了多份,所以本篇的题目注释叫(类型多例方式)。
因此,这种方法利弊共存,看你怎么想了。我是个人认为,除了浪费内存,没啥不好,简洁好维护。
所以就有了后面的“类型单例”方式。
本文完。