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++类和对象的更多相关文章

  1. 在 QML 中使用 C++ 类和对象

    Qt Quick 技术的引入,使得你能够快速构建 UI ,具有动画.各种绚丽效果的 UI 都不在话下.但它不是万能的,也有很多局限性,原来 Qt 的一些技术,比如低阶的网络编程如 QTcpSocket ...

  2. 危险代码:如何使用Unsafe操作内存中的Java类和对象

    危险代码:如何使用Unsafe操作内存中的Java类和对象—Part1 危险代码:如何使用Unsafe操作内存中的Java类和对象—Part2 危险代码:如何使用Unsafe操作内存中的Java类和对 ...

  3. 如何在JavaScript中手动创建类数组对象

    前言 关于什么是js的类数组对象这里不再赘述.可以参考这个链接,还有这里. js中类数组对象很多,概念简单的讲就是看上去像数组,又不是数组,可以使用数字下标方式访问又没有数组方法. 例: argume ...

  4. C++中如何定义类和对象?

    在C++语言中,对象的类型被称为类,类代表了某一批对象的共性和特征. 类是对象的抽象,而对象是类的具体实例.如同C中的结构体一样,我们要先定义一个结构体,再使用结构体去定义一个变量.同一个结构体可以定 ...

  5. C++类继承中,基类/当前对象属性/当前对象的构造顺序

    [1]中提到,规范的派生类构造函数三个要点: 首先创建基类对象 应通过成员初始化列表,创建基类对象 应该初始化本派生类新增的成员变量 那在构造派生类实例的过程中,其基类(以及多继承的时候多个基类)/当 ...

  6. java开发中的常见类和对象-建议阅读时间3分钟

    1.Dao 数据访问对象 此对象用于访问数据库.实现类一般用于用于操作数据库! 一般操作修改,添加,删除数据库操作的步骤很相似,就写了一个公共类DAO类 ,修改,添加,删除数据库操作时 直接调用公共类 ...

  7. 什么是“类数组对象”,在jquer中怎样将类数组对象转换为数组对象

    类数组对象的定义: 所谓"类数组对象"就是一个常规的Object对象,如$("div")但它和数组对象非常相似:具备length属性, 并以0.1.2.3……等 ...

  8. 在qml中使用model给委托对象MapPolylIne的path属性赋值。

    遇到两个崩溃的问题. 1.A线程中给赋值了变量 listA, 线程B中使用函数Add(QList<GeoPath> &list),由于在其函数中调用了list.at(index), ...

  9. python中面向对象_类_对象的概念与定义

    1. 面向对象的概念,面向对象是一种编程思想. 是对现实世界中一类事物的抽象,在编程中可以理解为是一种建立现实世界事物的模型 2.  面向对象和面向过程的区别: 面向过程关注的是完成工作的步骤. 面向 ...

随机推荐

  1. swoole创建TCP服务端和客户端

    服务端: server.php <?php //创建Server对象,监听 127.0.0.1:9501端口    $serv = new swoole_server("127.0.0 ...

  2. urllib.urlencode() 无法encode中文, UnicodeEncodeError

    urllib.urlencode() 无法encode中文, UnicodeEncodeError, 具体错误内容如下:File "/System/Library/Frameworks/Py ...

  3. github入门基础之上传本地文件以及安装github客户端

    github 不会使用,参照了其他大神的博客看的,很不错,就按步骤来,大家可以看看 http://www.cnblogs.com/wangzhongqiu/p/6243840.html

  4. Android 快速开发系列 ORMLite 框架最佳实践之实现历史记录搜索

    首先在build.gald中添加compile 'com.j256.ormlite:ormlite-android:4.48'的引用 compile 'com.j256.ormlite:ormlite ...

  5. MySql 查询列中包含数据库的关键字

    MySQL查询列表中包含数据的关键字的处理办法是用``把关键字包起来(tab键上面的字符)

  6. 【BZOJ1007】[HNOI2008]水平可见直线 半平面交

    [BZOJ1007][HNOI2008]水平可见直线 Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见 ...

  7. 爬虫入门【5】PyQuery简介

    PyQuery 目前最新的版本是1.3,基于最新版本进行介绍. 主要根据PyQuery的官方文档进行了更新. from pyquery import PyQuery as pq from lxml i ...

  8. [原创]webpack动态设置css路径

    在程序入口的最上方添加 __webpack_public_path__ = path; //your path //your app start here

  9. Office Web Apps Server 2013与PDF(二)

    在上一篇文章(Office Web Apps Server 2013与PDF(一))中,曾经介绍了Office Web Apps Server 2013在更新后,可以直接对PDF文档进行在线的查看.不 ...

  10. 九度OJ 1350:二叉树的深度 (二叉树)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1044 解决:614 题目描述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长 ...