QML::qml与c++数据交互

qml与c++数据交互

1.01 方式一:qmlRegisterType() 注册新的 C++ 类型、允许 QML 创建和使用自定义类型。
//1.0 c++类中使用Q_PROPERTY宏定义属性,使用绑定语法将属性与QML元素关联

#include <QObject>
class MyItem : public QObject
{
	Q_OBJECT
	 /* 使用 Q_PROPERTY 定义交互的属性 */
	Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChangeSig)
public:
	explicit MyItem(QObject *parent = nullptr) : QObject(parent), m_strItemName(""){}
	
	/* 为属性提供 getter 和 setter 方法 */
	void setName(QString name) {
		if(m_strItemName != name)
		{
			m_strItemName = name;
			emit nameChangeSig();
		}
	
	}
	QString getName(){
		return m_strItemName;
	}
	/* 将自定义 C++ 类型注册到 QML 中的函数*/
	static void registerQmlType(){
		qmlRegisterType<MyItem>("qmlMyItem", 1, 0, "MyItem");
	}
private:
	QString m_strItemName;
signals:
	/* 信号与属性对应,通过信号通知其他对象属性的变化 */
	void nameChangeSig();
public slots:
	void slotNameChange();
};
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include "myitem.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

     /* 将自定义 C++ 类型注册到 QML 中的函数*/
     //qmlRegisterType<MyItem>("qmlMyItem", 1, 0, "MyItem");
     MyItem::registerQmlType();

    QQmlApplicationEngine engine;
    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();
}
import QtQuick 2.12
import QtQuick.Window 2.12
/*引入c++类*/
import qmlMyItem 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    Rectangle{
        width: 50; height: 50;
        color: 'red'
        MouseArea {
            anchors.fill: parent
            onClicked: myItem.name = 'li'
        }
    }
   
    MyItem {
        id:myItem
        /*qml值改变,触发事件*/
        onNameChangeSig: {
            console.log('qml Name Changed')
            /*qml中通知c++对象*/
            myItem.slotNameChange()
        }
    }
}
1.02 qml中调用c++对象方法, 使用Q_INVOKABLE宏定义函数
(1) 在c++类中通过Q_INVOKABLE声明函数:
Q_INVOKABLEvoid setByName (QString name){m_strItemName = name;}
(2) 在qml中直接使用
myItem.setByName('xiaoming')

2.01 方式二:engine->rootContext()->setContextProperty(),注册单个对象实例、暴露特定的对象实例给 QML
// 在类中定义注册接口
void MainConfig::registerQml( QQmlEngine *engine ) {
    engine->rootContext()->setContextProperty( "MainConfig", this );
}
---------------------------------------------------------------
MainConfig::Instance()->registerQml( _engine );
Text {
	text: "应用程序名称: " + MainConfig.appName
	font.pixelSize: 18
	Layout.alignment: Qt.AlignHCenter
}

对比总结

特性 engine->rootContext()->setContextProperty() qmlRegisterType()
目的 注册单个对象实例 注册新的 C++ 类型
使用场景 暴露特定的对象实例给 QML 允许 QML 创建和使用自定义类型
访问方式 通过对象名称访问属性和方法 通过类型名称创建实例并访问属性和方法
生命周期管理 需要手动管理对象的生命周期 自动管理注册类型的生命周期
灵活性 更适合单一对象的交互 更适合多个实例的创建和管理

3.01 c++中的枚举在qml中注册使用
  • 用于在 QML 中注册一个不可创建的 C++ 枚举类型或命名空间。
  • 允许 QML 访问枚举值或常量,但不能直接实例化该元对象。
  • 适用于组织和管理全局常量和枚举类型。
 namespace MyNamespace {
   Q_NAMESPACE
   enum MyEnum {
       Key1,
       Key2,
   };
   Q_ENUM_NS(MyEnum)
 }
// 在类中定义注册接口
void MainConfig::registerQml( QQmlEngine *engine ) {
    engine->rootContext()->setContextProperty( "MainConfig", this );
    qmlRegisterUncreatableMetaObject(MyNamespace::staticMetaObject, "io.qt", 1, 0, "MyNamespace", 
        "Access to enums & flags only");
}

4.01 在 QML 文件中使用 pragma Singleton 指令来定义一个单例类型
  • 使用场景
    共享状态: 在整个应用程序中共享状态或配置。
    资源管理: 管理公共资源,如数据库连接、网络客户端等。
    全局设置: 提供全局的设置和配置选项。
// appVersionSingleton.qml
pragma Singleton
import QtQuick 2.15

QtObject {
    property string appName: "appVersionSingleton"
    property int version: 1

    function getApplicationInfo() {
        return `${appName} v${version}`;
    }
}
// 注册单例类型
qmlRegisterSingletonType<QObject>(
	"com.appversion.singleton",
	1,
	0,
	"appVersion",
	[](QQmlEngine *, QJSEngine *) -> QObject* {
	static QObject instance;
	return &instance;
	}
);
posted @   osbreak  阅读(154)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示