QT之在QML中使用C++类和对象
QML其实是对ECMAScript的扩展,融合了Qt object系统,它是一种新的解释性语言,QML引擎虽然由Qt C++实现,但QML对象的运行环境说到底和C++对象的上下文环境是不通的,是平行的两个世界,如果想在QML中访问C++对象,那么必然要找到一种途径在两个运行环境之间建立沟通的桥梁。
Qt提供了两种在QML环境中使用C++对象的方式:
(1)在C++中实现一个类,注册为QML环境的一个类型,在QML环境中使用该类型创建对象
(2)在C++中构造一个对象,将这个对象设置为QML的上下文属性,在QML环境中直接使用该属性
一 类的方式实现在QML中使用C++对象
1. 定义可以导出的C++类
要想将一个类或对象导出到QML中,必须满足以下几个条件:
(1)从QObject或QObject的派生类继承
(2)使用Q_OBJECT宏
(3)Q_INVOKABLE宏
在定义一个类的成员函数时使用Q_INVOKABLE宏来修饰,就可以让该方法被元对象系统调用,这个宏必须放在返回类型前面
(4)Q_ENUMS宏
如果要导出的类定义了想在QML中使用的枚举类型,可以使用Q_ENUM宏将该枚举注册到元对象系统中
(5)Q_PROPERTY宏
Q_PROPERTY宏用来定义可以通过元对象系统访问的属性,通过它定义的属性,可以在QML中访问,修改,也可以在属性变化时发射特定的信号
例子:
- #ifndef COLORMAKER_H
- #define COLORMAKER_H
- #include <QObject>
- #include <QColor>
- class ColorMaker : public QObject
- {
- Q_OBJECT
- Q_ENUMS(GenerateAlgorithm)
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(QColor timeColor READ timeColor)
- public:
- explicit ColorMaker(QObject *parent = nullptr);
- ~ColorMaker();
- enum GenerateAlgorithm
- {
- RandomRGB,
- RandomRed,
- RandomGreen,
- RandomBlue,
- LinearIcrease
- };
- QColor color() const {return m_currentColor;}
- void setColor(const QColor& color);
- QColor timeColor() const;
- Q_INVOKABLE GenerateAlgorithm alorithm() const;
- Q_INVOKABLE void serAlgorithm(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;
- };
- #endif // COLORMAKER_H
colormaker.h
- #include "colormaker.h"
- #include <QTime>
- #include <QTimerEvent>
- #include <QDebug>
- ColorMaker::ColorMaker(QObject *parent)
- : QObject(parent)
- ,m_algorithm(RandomRGB)
- ,m_currentColor(Qt::black)
- ,m_nColorTimer()
- {
- qsrand(QDateTime::currentDateTime().toTime_t());
- }
- ColorMaker::~ColorMaker()
- {
- }
- void ColorMaker::setColor(const QColor &color)
- {
- m_currentColor = color;
- emit colorChanged(color);
- }
- QColor ColorMaker::timeColor() const
- {
- QTime time = QTime::currentTime();
- qDebug() << time.toString("yyyy-MM-dd hh:mm:ss");
- int r = time.hour();
- int g = time.minute() * ;
- int b = time.second() * ;
- qDebug() << r << ":"<< g << ":"<< b;
- return QColor(r,g,b);
- }
- ColorMaker::GenerateAlgorithm ColorMaker::alorithm() const
- {
- return m_algorithm;
- }
- void ColorMaker::serAlgorithm(ColorMaker::GenerateAlgorithm algorithm)
- {
- m_algorithm = algorithm;
- }
- void ColorMaker::start()
- {
- qDebug() << "ColorMaker start";
- if (m_nColorTimer == )
- {
- m_nColorTimer = startTimer();
- }
- }
- void ColorMaker::stop()
- {
- if (m_nColorTimer > )
- {
- killTimer(m_nColorTimer);
- m_nColorTimer = ;
- }
- }
- void ColorMaker::timerEvent(QTimerEvent *e)
- {
- if (e->timerId() == m_nColorTimer)
- {
- switch (m_algorithm) {
- case RandomRGB:
- m_currentColor.setRgb(qrand()%, qrand()%,qrand()%);
- break;
- case RandomRed:
- m_currentColor.setRed(qrand()%);
- break;
- case RandomGreen:
- m_currentColor.setGreen(qrand()%);
- break;
- case RandomBlue:
- m_currentColor.setBlue(qrand()%);
- break;
- case LinearIcrease:
- {
- int r = m_currentColor.red() + ;
- int g = m_currentColor.green() + ;
- int b = m_currentColor.blue() + ;
- m_currentColor.setRgb(r%,g%,b%);
- }
- break;
- default:
- break;
- }
- emit colorChanged(m_currentColor);
- emit currentTime(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
- }
- else
- {
- return QObject::timerEvent(e);
- }
- }
colormaker.cpp
2. 注册QML类型
要注册一个QML类型,有多种方法:
qmlRegisterSingletonType()注册一个单例类型
qmlRegisterType()注册一个非单例类型
qmlRegisterTypeNotAvaliable()注册一个类型用来占位
qmlRegisterUncreatableType()通常用来注册一个具有附加属性的附加类型,具体参考Qt SDK
- template<typename T>
- int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
- template<typename T, int metaObjectRevision>
- int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
uri 指定唯一的包名
qmlname 是QML中可以使用的类名
- qmlRegisterType<ColorMaker>("an.qt.ColorMaker", , , "ColorMaker");
3. 在QML中导入类型
一旦你在C++中注册好了QML类型,就可以在QML文档中引入你注册的包,然后使用注册的类型了
- import an.qt.ColorMaker 1.0
- #include <QGuiApplication>
- #include <QQmlApplicationEngine>
- #include <QQuickView>
- #include <QtQml>
- #include "colormaker.h"
- int main(int argc, char *argv[])
- {
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- QGuiApplication app(argc, argv);
- //QQmlApplicationEngine engine;
- //engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
- //if (engine.rootObjects().isEmpty())
- // return -1;
- qmlRegisterType<ColorMaker>("an.qt.ColorMaker", , , "ColorMaker");
- QQuickView viewer;
- viewer.setResizeMode(QQuickView::SizeRootObjectToView);
- viewer.setSource(QUrl("qrc:///main.qml"));
- viewer.show();
- return app.exec();
- }
4. 在QML中创建由C++导出的类型的实例并使用
引入包后,你可以在QML中创建 C++导入类型的对象了,与QML内建类型的使用完全一样。
- Rectangle
- {
- width: ;
- height: ;
- ColorMaker
- {
- id:colorMaker;
- color:Qt.green;
- }
- }
例:
- import QtQuick 2.2
- import QtQuick.Window 2.2
- import QtQuick.Controls 1.4
- import QtQuick.Controls.Styles 1.4
- import QtQuick.Dialogs 1.3
- import QtQml 2.11
- import an.qt.ColorMaker 1.0
- Rectangle
- {
- width: ;
- height: ;
- Text {
- id: timeLabel;
- anchors.left: parent.left;
- anchors.leftMargin: ;
- anchors.top : parent.top;
- anchors.topMargin: ;
- font.pixelSize: ;
- }
- ColorMaker
- {
- id:colorMaker;
- color:Qt.green;
- }
- Rectangle
- {
- id:colorRect;
- anchors.centerIn: parent;
- width: ;
- height: ;
- color: "blue";
- }
- Button
- {
- id:start;
- text:"start";
- anchors.left: parent.left;
- anchors.leftMargin: ;
- anchors.bottom: parent.bottom;
- anchors.bottomMargin: ;
- onClicked:
- {
- console.log("start onClicked");
- colorMaker.start();
- }
- }
- Button
- {
- id:stop;
- text:"stop";
- anchors.left: start.right;
- anchors.leftMargin: ;
- anchors.bottom: start.bottom;
- anchors.bottomMargin: ;
- onClicked:
- {
- colorMaker.stop();
- }
- }
- function changeAlgorithm(button, algorithm)
- {
- switch(algorithm)
- {
- case :
- button.text = "RandomRGB"
- break;
- case :
- button.text ="RandomRed";
- break;
- case :
- button.text ="RandomGreen";
- break;
- case :
- button.text ="RandomBlue";
- break;
- case :
- button.text ="LinearIncrease";
- break;
- }
- }
- Button
- {
- id:colorAlgorithm;
- text:"RandomRGB";
- anchors.left:stop.right;
- anchors.leftMargin: ;
- anchors.bottom: stop.bottom;
- onClicked:
- {
- var algorithm = (colorMaker.alorithm() + ) % ;
- changeAlgorithm(colorAlgorithm,algorithm);
- colorMaker.serAlgorithm(algorithm);
- }
- }
- Button
- {
- id:quit
- text:"quit"
- anchors.left: colorAlgorithm.right;
- anchors.leftMargin: ;
- anchors.bottom: colorAlgorithm.bottom;
- onClicked:
- {
- Qt.quit();
- }
- }
- Component.onCompleted:
- {
- colorMaker.color = Qt.rgba(,,,);
- colorMaker.serAlgorithm(colorMaker.LinearIcrease);
- changeAlgorithm(colorAlgorithm,colorMaker.alorithm());
- }
- Connections
- {
- target: colorMaker;
- onCurrentTime:
- {
- timeLabel.text = strTime;
- console.log("onCurrentTime");
- // timeLabel.color = colorMaker.timeColor;
- }
- }
- Connections
- {
- target: colorMaker;
- onColorChanged:
- {
- colorRect.color = color;
- }
- }
- }
- /*Rectangle
- {
- width: 600
- height: 600
- Image {
- id: imageLabel;
- width: 600;
- height: 540;
- anchors.top: parent.top
- anchors.left: parent.left
- fillMode: Image.PreserveAspectFit
- source: "http://images.cnblogs.com/cnblogs_com/xiaobingqianrui/1185116/o_Image%201.png"
- }
- Button
- {
- id:openBtn
- width: 100;
- height: 40;
- text: "Open";
- anchors.top:imageLabel.bottom
- anchors.topMargin: 10;
- anchors.left: parent.left
- anchors.leftMargin: 10;
- onClicked:fileDialog.open();
- }
- Label
- {
- id:pathLabel;
- text: "Hello world"
- font.pixelSize: 22
- font.italic: true
- color: "steelblue"
- anchors.top:imageLabel.bottom
- anchors.topMargin: 10;
- anchors.left: openBtn.right
- anchors.leftMargin: 10
- }
- FileDialog
- {
- id:fileDialog
- title: "please choose a file"
- nameFilters: ["Image Files (*.jpg *.png *.gif)"]
- onAccepted:
- {
- imageLabel.source=fileDialog.fileUrl;
- console.log(fileDialog.fileUrl);
- var imageFile = new String(fileDialog.fileUrl);
- pathLabel.text=imageFile.slice(8);
- }
- }
- }*/
二 对象的方式实现在QML中使用C++对象
1. 注册属性
- viewer.rootContext()->setContextProperty("colorMaker", new ColorMaker);
2. 在QML中使用关联到的C++对象的属性
一旦调用setContextProperty()导出了属性,就可以在QML中使用了,不需要import语句
- import QtQuick 2.2
- import QtQuick.Window 2.2
- import QtQuick.Controls 1.4
- import QtQuick.Controls.Styles 1.4
- import QtQuick.Dialogs 1.3
- import QtQml 2.11
- //import an.qt.ColorMaker 1.0
- Rectangle
- {
- width: ;
- height: ;
- Text {
- id: timeLabel;
- anchors.left: parent.left;
- anchors.leftMargin: ;
- anchors.top : parent.top;
- anchors.topMargin: ;
- font.pixelSize: ;
- }
- /* ColorMaker
- {
- id:colorMaker;
- color:Qt.green;
- }*/
- Rectangle
- {
- id:colorRect;
- anchors.centerIn: parent;
- width: ;
- height: ;
- color: "blue";
- }
- Button
- {
- id:start;
- text:"start";
- anchors.left: parent.left;
- anchors.leftMargin: ;
- anchors.bottom: parent.bottom;
- anchors.bottomMargin: ;
- onClicked:
- {
- console.log("start onClicked");
- colorMaker.start();
- }
- }
- Button
- {
- id:stop;
- text:"stop";
- anchors.left: start.right;
- anchors.leftMargin: ;
- anchors.bottom: start.bottom;
- anchors.bottomMargin: ;
- onClicked:
- {
- colorMaker.stop();
- }
- }
- function changeAlgorithm(button, algorithm)
- {
- switch(algorithm)
- {
- case :
- button.text = "RandomRGB"
- break;
- case :
- button.text ="RandomRed";
- break;
- case :
- button.text ="RandomGreen";
- break;
- case :
- button.text ="RandomBlue";
- break;
- case :
- button.text ="LinearIncrease";
- break;
- }
- }
- Button
- {
- id:colorAlgorithm;
- text:"RandomRGB";
- anchors.left:stop.right;
- anchors.leftMargin: ;
- anchors.bottom: stop.bottom;
- onClicked:
- {
- var algorithm = (colorMaker.alorithm() + ) % ;
- changeAlgorithm(colorAlgorithm,algorithm);
- colorMaker.serAlgorithm(algorithm);
- }
- }
- Button
- {
- id:quit
- text:"quit"
- anchors.left: colorAlgorithm.right;
- anchors.leftMargin: ;
- anchors.bottom: colorAlgorithm.bottom;
- onClicked:
- {
- Qt.quit();
- }
- }
- Component.onCompleted:
- {
- colorMaker.color = Qt.rgba(,,,);
- //colorMaker.serAlgorithm(colorMaker.LinearIcrease);
- colorMaker.serAlgorithm();
- changeAlgorithm(colorAlgorithm,colorMaker.alorithm());
- }
- Connections
- {
- target: colorMaker;
- onCurrentTime:
- {
- timeLabel.text = strTime;
- console.log("onCurrentTime");
- // timeLabel.color = colorMaker.timeColor;
- }
- }
- Connections
- {
- target: colorMaker;
- onColorChanged:
- {
- colorRect.color = color;
- }
- }
- }
QT之在QML中使用C++类和对象的更多相关文章
- 在 QML 中使用 C++ 类和对象
Qt Quick 技术的引入,使得你能够快速构建 UI ,具有动画.各种绚丽效果的 UI 都不在话下.但它不是万能的,也有很多局限性,原来 Qt 的一些技术,比如低阶的网络编程如 QTcpSocket ...
- 危险代码:如何使用Unsafe操作内存中的Java类和对象
危险代码:如何使用Unsafe操作内存中的Java类和对象—Part1 危险代码:如何使用Unsafe操作内存中的Java类和对象—Part2 危险代码:如何使用Unsafe操作内存中的Java类和对 ...
- 如何在JavaScript中手动创建类数组对象
前言 关于什么是js的类数组对象这里不再赘述.可以参考这个链接,还有这里. js中类数组对象很多,概念简单的讲就是看上去像数组,又不是数组,可以使用数字下标方式访问又没有数组方法. 例: argume ...
- C++中如何定义类和对象?
在C++语言中,对象的类型被称为类,类代表了某一批对象的共性和特征. 类是对象的抽象,而对象是类的具体实例.如同C中的结构体一样,我们要先定义一个结构体,再使用结构体去定义一个变量.同一个结构体可以定 ...
- C++类继承中,基类/当前对象属性/当前对象的构造顺序
[1]中提到,规范的派生类构造函数三个要点: 首先创建基类对象 应通过成员初始化列表,创建基类对象 应该初始化本派生类新增的成员变量 那在构造派生类实例的过程中,其基类(以及多继承的时候多个基类)/当 ...
- java开发中的常见类和对象-建议阅读时间3分钟
1.Dao 数据访问对象 此对象用于访问数据库.实现类一般用于用于操作数据库! 一般操作修改,添加,删除数据库操作的步骤很相似,就写了一个公共类DAO类 ,修改,添加,删除数据库操作时 直接调用公共类 ...
- 什么是“类数组对象”,在jquer中怎样将类数组对象转换为数组对象
类数组对象的定义: 所谓"类数组对象"就是一个常规的Object对象,如$("div")但它和数组对象非常相似:具备length属性, 并以0.1.2.3……等 ...
- 在qml中使用model给委托对象MapPolylIne的path属性赋值。
遇到两个崩溃的问题. 1.A线程中给赋值了变量 listA, 线程B中使用函数Add(QList<GeoPath> &list),由于在其函数中调用了list.at(index), ...
- python中面向对象_类_对象的概念与定义
1. 面向对象的概念,面向对象是一种编程思想. 是对现实世界中一类事物的抽象,在编程中可以理解为是一种建立现实世界事物的模型 2. 面向对象和面向过程的区别: 面向过程关注的是完成工作的步骤. 面向 ...
随机推荐
- 安装Hadoop 1.1.2 (二 安装配置SSH)
1 查找SSH yum search ssh 2 如果没有安装, yum install openssh.x86_64 4 直接运行 ssh-keygen -t dsa -P '' -f /roo ...
- 2218 补丁vs错误
2218 补丁vs错误 1999年CTSC国家队选拔赛 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 大师 Master 题解 题目描述 Description 错 ...
- <转载> 为什么在Python里推荐使用多进程而不是多线程?
经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢? 要知其然,更要知其所以然.所以有了下面的深入研究: 首先强调背景: ...
- 如何将gedit变成c++编译器
本蒟蒻的第一篇文章,分享一下神佬教我的好东西 ——将Ubuntu 16.04上gedit变为编译器! 1° 新建文档.然后点击编辑,打开首选项. 2° 勾选外部工具,然后退出.打开工具,选择Manag ...
- go语言之面向对象一
在Go语言中, 你可以给任意类型(包括内置类型,但不包括指针类型)添加相应的办法.示例如下: type Integer int func (a Integer) Less(b Integer) boo ...
- centos7 使用 maven
http://www.cnblogs.com/jackluo/archive/2013/02/06/2901816.html
- 只需两步删除 node_modules
peng@PENG-PC /E/_My_File_____/home/learn/web_qianduan/mithril-demo/demo2/mithril -demo $ npm install ...
- 关于VMAX中存储资源池(SRP)
Storage Resource Pool中的相关元素 SRP由一个或多个数据池组成,这些数据池包含了预配置的数据(或TDAT)设备,可为创建和呈现给主机与应用程序的精简设备(TDEVS) 提供存储. ...
- R中常用数据挖掘算法包
数据挖掘主要分为4类,即预测.分类.聚类和关联,根据不同的挖掘目的选择相应的算法.下面对R语言中常用的数据挖掘包做一个汇总: 连续因变量的预测: stats包 lm函数,实现多元线性回归 stats包 ...
- Oracle数据库体系结构(3)数据库进程
一.Oracle进程概述 在oracle中进程分为用户进程(User Process).服务器进程(server process)和后天进程3种. 1.用户进程:当用户连接到数据库执行一个应用程序是, ...