QML(15)——QML与C++交互方式总结2/3(qml调用C++的成员属性)

本文详细介绍了如何在Qt QML中调用C++对象的成员属性和信号函数。首先展示了C++类的定义,包括Q_PROPERTY的使用,然后讲解了两种注册C++类到QML的方式,最后通过实例展示了在QML中如何直接使用或像组件一样使用C++对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、目的

qml文件中,可以调用C++对象的成员属性(变量),及对应的信号函数

二、步骤

1、C++类文件

创建C++文件时,一定要勾选下面3项

MyQmlClass.h


#ifndef MYQMLCLASS_H
#define MYQMLCLASS_H

#include <QObject>

class MyQmlClass : public QObject {
  Q_OBJECT
  // 暴露成员属性
  Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
  Q_PROPERTY(int year READ getYear WRITE setYear NOTIFY yearChanged)

 public:
  explicit MyQmlClass(QObject *parent = nullptr);

  // 属性对应的接口函数
  void setName(const QString &name);    
  QString getName() const;

  void setYear(int year);
  int getYear() const;

 signals:
  // 属性对应的信号函数
  void nameChanged(const QString name);
  void yearChanged(int year);


 private:
  // 成员变量 / 属性
  QString m_Name;
  int m_Year;
};

#endif  // MYQMLCLASS_H

选项说明

其实我们在实际使用中,很少能够用全 Q_PROPERTY 的所有选项,这里介绍些常用的选项:

  • type 是属性的类型,可以是 int、QString、QObject、QColor 等等,name 就是属性的名字。

  • READ 标记,如果你没有为属性指定 MEMBER 标记,则 READ 标记必不可少。声明一个读取属性的函数,该函数一般没有参数,返回定义的属性。

  • WRITE 标记,可选配置。声明一个设定属性的函数。它指定的函数,只能有一个与属性类型匹配的参数,必须返回 void 。

  • NOTIFY 标记,可选配置。给属性关联一个信号(该信号必须是已经在类中声明过的),当属性的值发生变化时就会触发该信号。信号的参数,一般就是你定义的属性。

MyQmlClass.cpp


#include "myqmlclass.h"
#include <QDebug>

MyQmlClass::MyQmlClass(QObject *parent)
    : QObject(parent), m_Name("xingxing"), m_Year(20) {}

void MyQmlClass::setName(const QString &name) {
  qDebug() << "MyQmlClass::setName";
  if (m_Name != name) {
    qDebug() << "emit namechanged";
    m_Name = name;
    // 触发信号是emit控制,信号和槽 是connect控制
    emit nameChanged(name);
  }
}

QString MyQmlClass::getName() const {
  qDebug() << "MyQmlClass::getName";
  return m_Name;
}

void MyQmlClass::setYear(int year) {
  qDebug() << "MyQmlClass::setYear";
  if (m_Year != year) {
    qDebug() << "emit yearchanged";
    m_Year = year;
    emit yearChanged(m_Year);
  }
}

int MyQmlClass::getYear() const {
  qDebug() << "MyQmlClass::getYear";
  return m_Year;
}

2、注册

注册有两种方式

方式1:  engine.rootContext()->setContextProperty("myQml", &myQmlImp);

main.cpp


#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "myqmlclass.h"

int main(int argc, char *argv[]) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
  QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

  QGuiApplication app(argc, argv);

  QQmlApplicationEngine engine;

  //【 方式1:创建一个C++对象,注册给qml使用 】
  MyQmlClass myQmlImp;
  engine.rootContext()->setContextProperty("myQml", &myQmlImp);


  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();
}

方式2:qmlRegisterType<MyQmlClass>("MyClass.module", 1, 0, "MyQml");

main.cpp


#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "myqmlclass.h"

int main(int argc, char *argv[]) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
  QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

  QGuiApplication app(argc, argv);

  QQmlApplicationEngine engine;
  
  //【方式2: 把整个C++类注册到qml,作为qml的一个组件对象】
  qmlRegisterType<MyQmlClass>("MyClass.module", 1, 0, "MyQml");

  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();
}

3、qml中使用

3.1

如果注册时使用方式1,qml中可以直接使用 注册名.function()myQml.getValue()

使用这种方式时,IDE不会自动提示相关关键字,但是完成后运行实现了效果。

具体使用场景可看 上一篇博文:
https://blog.youkuaiyun.com/wangpailiulanqi8/article/details/124625817

3.2

如果注册时使用方式2,使用C++类就像QML 的组件一样,需要导库,创建,调用

Register03.qml

import QtQuick 2.0
import QtQuick.Controls 2.15
import MyClass.module 1.0

Item {
    id: root

    //cpp类作为一个qml对象
    MyQml {
        id: cpp_obj
        property int counts: 0

        //qml对象的每个属性都有对应的onPropertyChanged
        onYearChanged: {
            console.log("onYearChanged ", year)
            counts++
        }
        onCountsChanged: {
            console.log("onCountsChanged ", counts)
            name = "NAMECHANGE"
        }
        onNameChanged: {
            console.log("onNameChanged ", name)
        }
    }

    MouseArea {
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        onClicked: {
            if (mouse.button === Qt.LeftButton) {
                console.log("--- 点击左键:cpp发出信号")
                // 修改属性 触发cpp信号函数 namechanged
                cpp_obj.name = "wangyue"
                cpp_obj.year = 1996
               } 
        }
    }


}
main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Loader {
        id: contentPane
        anchors.fill: parent
    }

    Component.onCompleted: contentPane.source = "qrc:/Register03.qml"
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值