背景:
之前学习qml特意总结了几种qml与c++交互的模式,先提炼一下我认为重要的。
【qml-5.1】qml与c++交互(QML_ELEMENT/QML_SINGLETON)(本文)
由于项目中多次用到,真心觉得,"类型单例"模式是最适合全局使用的,"类型多例"目前也就分页组件用过。我认为这两种方式目前为止最好用。所谓好用是指:代码量不大,qml中可以自动补全提示。
但是,在不断学习过程中,对一个词比较敏感和青睐,那就是"更现代的"。所以就想再次尝试总结使用宏的方式实现交互。亦即:QML_ELEMENT/QML_SINGLETON。
下面就是实验过程,直接说主要步骤。
环境:
能选就选最新的,我这目前不是最新,是qt6.9.3。
新建了一个compat类型的工程,亦即使用qrc资源模式。
个人推荐这种模式,ui可以用qds做好,选择生成qrc文件,或者不用也行,我的习惯永远是最小侵入或最小污染原则。所以qds好些自动功能一律不用,只要它生成的qml文件,和那个images图片文件目录。然后用creator新建工程,把那个qml目录content和qrc文件复制过去。
类定义:
直接在qt creator中选择添加c++类,过程中会让你选择,我选择了继承自QObject亦即添加宏。


于是生成了:
cpp
#ifndef CPP_H
#define CPP_H
#include <QObject>
#include <QQmlEngine>
#include <QDebug>//I added
class Cpp : public QObject
{
Q_OBJECT
QML_ELEMENT
public:
explicit Cpp(QObject *parent = nullptr);
Q_INVOKABLE void f() { qDebug() << __FUNCTION__; }//I added
signals:
};
#endif // CPP_H
我加了个函数,输出函数名,不用多说了。想要qml能调用,记着加Q_INVOKABLE。
Cmake:
CMakeLists中添加一段:
cpp
qt_policy(SET QTP0001 NEW)
qt6_add_qml_module(${PROJECT_NAME}
URI CppType
VERSION 1.0
SOURCES
cpp.cpp cpp.h
)
URI对应的是qml中import那个名字,亦即模块。比如按照我的习惯,所有单例注册到CppSingleton,多例注册到CppType,就这个意思。
版本号不用说了。然后就没然后了。
Qml:

各位看这个德行,我就贼不喜欢这样!运行一下看看:

看,成功了是吧?
这是多例模式的体现。
类型单例:
如果要单例模式,就要定义类的时候加个宏:
cpp
#ifndef CPP_H
#define CPP_H
#include <QObject>
#include <QQmlEngine>
#include <QDebug>
class Cpp : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON//就是这里!
public:
explicit Cpp(QObject *parent = nullptr);
Q_INVOKABLE void f() { qDebug() << __FUNCTION__; }
signals:
};
#endif // CPP_H
然后就啥也不用动,还是上面那样。只不过qml中需要改一下调用方法:
javascript
import QtQuick 2.15
import QtQuick.Window 2.15
import CppType 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
// Cpp { id: cpp }
// Component.onCompleted: cpp.f()
Component.onCompleted: Cpp.f()//注意这里!
}
然后就没然后了。简单吧?当然按照我的习惯,cmake那里添加模块时,我会让URI是CppSingleton,然后qml的import那里也要改。只不过这里我沿用了上文的,就为说明问题而已,就不较真了。
都不用工厂函数之类的,具体参考之前的博客"类型单例"模式。
总结:
各位说这事简单不?按理说确实挺现代的,非常简练。
但是我不爽啊,qml里那个报错,试过很多次了,只能重启creator,还不保证一定能行。等于非要自己记着没错才可以。反正目前我没试出好办法,AI也胡说八道,没个正经法。最后逼急了它说等着qt升级完善。
总之别忘了咱的原则:最小污染,最小侵入,简洁简练稳定。
各位老少爷们,有好办法说一声。