当前位置: 首页 > news >正文

QML与C++通信

一、QML中如何使用C++的类和对象

前提条件:
1.从 QObject 或 QObject 的派生类继承
2.使用 Q_OBJECT 宏
这两个条件是为了让一个类能够进入 Qt 强大的元对象系统(meta-object system)中,只有使用元对象系统,一个类的某些方法或属性才可能通过字符串形式的名字来调用,才具有了在 QML 中访问的基础条件。
一旦导出了一个类,在 QML 中就必然要访问该类的实例的属性或方法来达到某种目的,而具有什么特征的属性或方法才可以被 QML 访问呢?

信号和槽(针对C++中类的函数而言)
class ColorMaker : public QObject
{Q_OBJECTpublic:ColorMaker(QObject *parent = 0);~ColorMaker();signals:void colorChanged(const QColor & color);void currentTime(const QString &strTime);public slots:void start();void stop();};

我们定义了 start() / stop() 两个槽, colorChanged() / currentTime() 两个信号,都可以在 QML 中通过对象的方法直接使用,例如:

ColorMaker{id:colormaker
}
colormaker.start();或者colormaker.colorChanged(color);
使用Q_INVOKABLE 宏修饰的普通函数(针对C++中类的函数而言)

在定义一个类的成员函数时使用 Q_INVOKABLE 宏来修饰,使用 Q_INVOKABLE 将某个方法注册到元对象系统中,就可以让该方法被元对象系统调用。这个宏必须放在返回类型前面。

class ColorMaker : public QObject
{Q_OBJECTpublic:ColorMaker(QObject *parent = 0);~ColorMaker();Q_INVOKABLE GenerateAlgorithm algorithm() const;Q_INVOKABLE void setAlgorithm(GenerateAlgorithm algorithm);signals:void colorChanged(const QColor & color);void currentTime(const QString &strTime);public slots:void start();void stop();
};

algorithm()和setAlgorithm(GenerateAlgorithm algorithm)都可以在在 QML 中通过对象的方法直接使用,例如:

ColorMaker{id:colormaker
}
colormaker.algorithm();
使用Q_ENUMS 宏修饰的枚举类型(针对C++中类的枚举类型而言)
class ColorMaker : public QObject
{Q_OBJECTQ_ENUMS(GenerateAlgorithm)
public:ColorMaker(QObject *parent = 0);~ColorMaker();enum GenerateAlgorithm{RandomRGB,RandomRed,RandomGreen,RandomBlue,LinearIncrease};Q_INVOKABLE GenerateAlgorithm algorithm() const;Q_INVOKABLE void setAlgorithm(GenerateAlgorithm algorithm);signals:void colorChanged(const QColor & color);void currentTime(const QString &strTime);public slots:void start();void stop();
};

QML中可通过ColorMaker.LinearIncrease直接使用。

使用Q_PROPERTY 宏修饰的变量类型(针对C++中类的变量而言)
class QQuickText : public QQuickImplicitSizeItem
{Q_OBJECTQ_ENUMS(HAlignment)Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)...  
public:...
};

综合运用上述方法和属性:

class ColorMaker : public QObject
{Q_OBJECTQ_ENUMS(GenerateAlgorithm)Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)Q_PROPERTY(QColor timeColor READ timeColor)
public:ColorMaker(QObject *parent = 0);~ColorMaker();enum GenerateAlgorithm{RandomRGB,RandomRed,RandomGreen,RandomBlue,LinearIncrease};QColor color() const;void setColor(const QColor & color);QColor timeColor() const;Q_INVOKABLE GenerateAlgorithm algorithm() const;Q_INVOKABLE void setAlgorithm(GenerateAlgorithm algorithm);signals:void colorChanged(const QColor & color);void currentTime(const QString &strTime);public slots:void start();void stop();protected:void timerEvent(QTimerEvent *e);private:GenerateAlgorithm m_algorithm;QColor m_currentColor;int m_nColorTimer;
};

(一)QML中使用C++中的类

方法:在 C++ 中实现一个类,注册到 QML 环境中, QML 环境中使用该类型创建对象

要注册一个 QML 类型,有多种方法可用,如 qmlRegisterSingletonType() 用来注册一个单例类型, qmlRegisterType() 注册一个非单例的类型, qmlRegisterTypeNotAvailable() 注册一个类型用来占位, qmlRegisterUncreatableType() 通常用来注册一个具有附加属性的附加类型
qmlRegisterType() 是个模板函数

template<typename T>
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);

使用qmlRegisterType 需要包含 QtQml 头文件。
先说模板参数 typename ,它就是你实现的 C++ 类的类名。
qmlRegisterType() 的第一个参数 uri ,让你指定一个唯一的包名,类似 Java 中的那种,一是用来避免名字冲突,而是可以把多个相关类聚合到一个包中方便引用。比如我们常写这个语句 “import QtQuick.Controls 1.1” ,其中的 “QtQuick.Controls” 就是包名 uri ,而 1.1 则是版本,是 versionMajor 和 versionMinor 的组合。 qmlName 则是 QML 中可以使用的类名。

#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QtQml>
#include "colorMaker.h"int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);qmlRegisterType<ColorMaker>("an.qt.ColorMaker", 1, 0, "ColorMaker");QtQuick2ApplicationViewer viewer;viewer.setMainQmlFile(QStringLiteral("qml/colorMaker/main.qml"));viewer.showExpanded();return app.exec();
}

上面的代码将 ColorMaker 类注册为 QML 类 ColorMaker ,主版本为 1 ,次版本为 0 ,而我起的包名则是 an.qt.ColorMaker 。注册动作一定要放在 QML 上下文创建之前。

QML中使用此类的方法:

import an.qt.ColorMaker 1.0
Rectangle {width: 360;height: 360;ColorMaker {id: colorMaker;color: Qt.green;}
}

(二)QML中使用C++中的对象

方法:在 C++ 中构造一个对象,将这个对象设置为 QML 的上下文属性,在 QML 环境中直接使用该属性
可以把 C++ 中创建的对象作为属性传递到 QML 环境中,然后在 QML 环境中访问。
main.cpp:

 QQmlContext *context = engine.rootContext();context->setContextProperty("myobject", myobject);

还有一点要说明,因为去掉了 qmlRegisterType() 调用,所以在 main.qml 中不能再访问 ColorMaker 类了,比如你不能通过类名来引用它定义的 GenerateAlgorithm 枚举类。
此种方法QML中无需import导入,可以直接使用myobject对象访问其属性和方法,例如myobject.iValue

二、C++中使用QML中的函数

QML 对象对应的类型,原本就是 C++ 类型,比如 Image 对应 QQuickImage , Text 对应 QQuickText……但是,这些与 QML 类型对应的 C++ 类型都是私有的,你写的 C++ 代码也不能直接访问。肿么办?
Qt 最核心的一个基础特性,就是元对象系统,通过元对象系统,你可以查询 QObject 的某个派生类的类名、有哪些信号、槽、属性、可调用方法等等信息,然后也可以使用 QMetaObject::invokeMethod() 调用 QObject 的某个注册到元对象系统中的方法。而对于使用 Q_PROPERTY 定义的属性,可以使用 QObject 的 property() 方法访问属性,如果该属性定义了 WRITE 方法,还可以使用 setProperty() 修改属性。所以只要我们找到 QML 环境中的某个对象,就可以通过元对象系统来访问它的属性、信号、槽等。

 engine.load(url);auto list = engine.rootObjects();auto window = list.first();//auto name = window->objectName();//QObject* obj =  window->findChild<QObject*>("myobjects");//myobjects为某个控件的objectnameqDebug() << obj;QVariant res;QVariant arg = 15;QMetaObject::invokeMethod(obj, "func", Q_RETURN_ARG(QVariant, res),Q_ARG(QVariant,arg));qDebug() << res;return app.exec();

参考文章:http://blog.csdn.net/foruok

相关文章:

  • Python电梯楼层数字识别
  • STM32第九节(中级篇):RCC(第一节)——时钟树讲解
  • Tomcat的部署及调优,jvm调优
  • Java8 新特性
  • Java-并发编程--ThreadLocal、InheritableThreadLocal
  • 《LeetCode热题100》笔记题解思路技巧优化_Part_3
  • QT 状态机的使用
  • RocketMQ架构详解
  • 17个工作必备的Python自动化代码分享(上篇)
  • 泽众云真机-机型支持ADB调试功能即将上线
  • 进程学习--02
  • 有来团队后台项目-解析7
  • 鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Web)中篇
  • Postman请求API接口测试步骤和说明
  • C#使用SharpZipLib对文件进行压缩和解压
  • interface和setter,getter
  • Linux链接文件
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Service Worker
  • Spring声明式事务管理之一:五大属性分析
  • Xmanager 远程桌面 CentOS 7
  • 大主子表关联的性能优化方法
  • 浏览器缓存机制分析
  • 前端技术周刊 2019-01-14:客户端存储
  • 世界上最简单的无等待算法(getAndIncrement)
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 正则表达式小结
  • 说说我为什么看好Spring Cloud Alibaba
  • ​用户画像从0到100的构建思路
  • # 数论-逆元
  • %check_box% in rails :coditions={:has_many , :through}
  • (11)MATLAB PCA+SVM 人脸识别
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (转)c++ std::pair 与 std::make
  • (转)视频码率,帧率和分辨率的联系与区别
  • *1 计算机基础和操作系统基础及几大协议
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .NET Core中Emit的使用
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • [20190401]关于semtimedop函数调用.txt
  • [AIGC codze] Kafka 的 rebalance 机制
  • [Android学习笔记]ScrollView的使用
  • [BIZ] - 1.金融交易系统特点
  • [codevs] 1029 遍历问题
  • [Contest20180313]灵大会议
  • [Flex][问题笔记]TextArea滚动条问题
  • [HackMyVM]靶场 Wild
  • [hdu1561] The more, The Better 【树形DP】