1.C++注册到QML系统
第一步:依然需要新建一个类QmlCpp:
qmlcpp.h文件:
#ifndef QMLCPP_H
#define QMLCPP_H
#include <QObject>
class QmlCpp : public QObject
{
Q_OBJECT
public:
explicit QmlCpp(QObject *parent = nullptr);
Q_INVOKABLE void setValue(int nValue);
Q_INVOKABLE int getValue();
signals:
public slots:
private:
int m_nValue;
};
依然需要使用 Q_INVOKABLE 这个宏声明两个成员函数,将函数申明为元对象系统可调用的函数。
第二步:在main.cpp中进行注册:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "qmlcpp.h"
#include <QQmlEngine>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<QmlCpp>("myqml",1,0,"QmlCpp");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
关键语句:
qmlRegisterType<QmlCpp>("myqml",1,0,"QmlCpp");
其中myqml是QML中的组件吗名,1.0是组件版本号,QmlCpp是用于QML中的类名。
第三步:修改一下QML文件:
import QtQuick 2.12
import QtQuick.Controls 2.12
import myqml 1.0
Item {
QmlCpp{
id:qmlpro
}
Button{
id:btn
height: 48
width: 120
text: "1"
anchors.centerIn: parent
onClicked: {
text=qmlpro.getValue();
console.log(text);
}
}
Button{
id:btn1
height: 48
width: 120
anchors.top: btn.bottom
anchors.topMargin: 12
anchors.horizontalCenter: btn.horizontalCenter
onClicked: {
var value = qmlpro.getValue()
qmlpro.setValue(++value)
}
}
}
其中第三行 import myqml 1.0 是我们在 main.cpp中进行注册了类型的版本化命名空间。
QmlCpp{
id:qmlpro
}
导入之后,就可以如上所示 调用QmlCpp进行实例化,并设置id为qmlpro.
在两个button的点击事件中,就能通过 实例化对象 qmlpro调用 第一步 被 Q_INVOKABLE声明的函数了。
分割线上面部分是将一个C++类注册到了QML系统中,还有另外一种注册方式:
2.将单例函数注册到QML系统中:
第一步:先创建一个单例函数
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "qmlcpp.h"
#include <QJSValue>
#include <QQmlEngine>
static QJSValue singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine)
static int nValue = 5;
QJSValue example = scriptEngine->newObject();
example.setProperty("nValue",nValue++);
return example;
}
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterSingletonType("myJsvalueApi", 1, 0, "MyQmlFunction", singletontype_provider);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
在函数名为 singletontype_provider的函数中,将整型 nValue 的值通过setProperty(name,value)设置为这个单例函数的属性,以便我们在QML文件中可以访问它。
在main()函数中,注册函数为:
qmlRegisterSingletonType("myJsvalueApi", 1, 0, "MyQmlFunction", singletontype_provider);
其中 myJsvalueApi 1.0 依然是注册了类型的版本化命名空间,而这一次注册的类型是一个单例函数 singletontype_provider,在Qml文件中调用这个函数则使用 第三个参数 MyQmlFunction,(注意 首字母必须大写,小写就会报错),调用示例如下:
import QtQuick 2.12
import QtQuick.Controls 2.12
//import myqml 1.0
import myJsvalueApi 1.0
Item {
Button{
id:btn
height: 48
width: 120
text: "1"
anchors.centerIn: parent
onClicked: {
text = MyQmlFunction.nValue;
}
}
Button{
id:btn1
height: 48
width: 120
anchors.top: btn.bottom
anchors.topMargin: 12
anchors.horizontalCenter: btn.horizontalCenter
onClicked: {
MyQmlFunction.nValue++;
}
}
}
import myJsvalueApi 1.0
先导入在main函数中注册的带版本的命名空间,调用单例函数中的属性值 nValue直接使用:
MyQmlFunction.nValue++;
3.QML中接受C++信号:
第一步:在addValue()函数中发射信号:
void QmlCpp::addValue(int nValue)
{
m_nValue += nValue;
emit valueChanged();
}
第二步:在QML中创建QmlCpp的对象,并设置信号接收函数:
import QtQuick 2.12
import QtQuick.Controls 2.12
import myqml 1.0
//import myJsvalueApi 1.0
Item {
QmlCpp{
id:qmlpro
value:111
onValueChanged:{
btn.text = qmlpro.value
}
}
Button{
id:btn
height: 48
width: 120
text: "1"
anchors.centerIn: parent
onClicked: {
qmlpro.addValue(10);
text= qmlpro.value
console.log(text)
}
}
Button{
id:btn1
height: 48
width: 120
anchors.top: btn.bottom
anchors.topMargin: 12
anchors.horizontalCenter: btn.horizontalCenter
onClicked: {
qmlpro.value++;
}
}
}
注意:在QmlCpp类中定义的信号是 valueChanged(),在Qml中进行监听 需要在前面加 “on”,首字母大写,变为onValueChanged:{}
总结:本篇博客 叙述了 将C++注册进入QML系统中,并访问C++类的成员函数、槽函数、并接受C++发出的信号。
将C++类注册进元对象系统 和 QML系统 区别:
-
注册进元对象系统,需要在main.cpp中实现C++类的实例化。
-
注册进QML系统环境中,在QML文件中实现对C++类的实例化,并且可以直接接收C++发射过来的信号。
-
两种方式的注册方式略有不同。