Qt5处于过度阶段,架构繁琐,学习成本不低。尤其是UI代码竟然被重写,变了天。

Qt中的c++可能是连接OPENCV与QML的一个不错的桥梁,在此学习这部分实用的技术。

Reference: http://blog.csdn.net/foruok/article/details/32698603

一、在 QML 中调用 c++

  1. 实现 c++类

  2. 注册 QML 类型

  3. 在 QML 中导入类型

  4. 在 QML 创建由 C++ 导出的类型的实例并使用

Qt 提供了两种在 QML 环境中使用 C++ 对象的方式:

  1. 在 C++ 中实现一个,注册到 QML 环境中, QML 环境中使用该类型创建对象
  2. 在 C++ 中构造一个对象,将这个对象设置为 QML 的上下文属性,在 QML 环境中直接使用改属性

对要导出的 C++ 类都有要求,不是一个类的所有方法、变量都可以被 QML 使用。

因此我们先来看看怎样让一个方法属性可以被 QML 使用。


对要导出的 C++ 类都有要求,不是一个类的所有方法、变量都可以被 QML 使用。

从 QObject 或 QObject 的派生类继承
使用 Q_OBJECT 宏

信号,槽 可以直接被调用 (方法)

成员函数时使用 Q_INVOKABLE 宏来修饰,可以让该方法被元对象系统调用。

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

QML 中使用 ${Object}.${method} 来访问:

Component.onCompleted: {
colorMaker.color = Qt.rgba(,,, );
colorMaker.setAlgorithm(ColorMaker.LinearIncrease);
changeAlgorithm(colorAlgorithm, colorMaker.algorithm());
}

Q_PROPERTY 宏  (属性)

Q_PROPERTY 宏用来定义可通过元对象系统访问的属性。

通过它定义的属性,可以在 QML 中访问、修改,也可以在属性变化时发射特定的信号。

要想使用 Q_PROPERTY 宏,你的类必须是 QObject 的后裔,必须在类首使用 Q_OBJECT 宏。

比较常用的是 READ / WRITE / NOTIFY 三个选项。我们来看看都是什么含义。
  • READ 标记  如果你没有为属性指定 MEMBER 标记,则 READ 标记必不可少;声明一个读取属性的函数,该函数一般没有参数,返回定义的属性。
  • WRITE 标记  可选配置。声明一个设定属性的函数。它指定的函数,只能有一个与属性类型匹配的参数,必须返回 void 。
  • NOTIFY 标记   可选配置。给属性关联一个信号(该信号必须是已经在类中声明过的),当属性的值发生变化时就会触发该信号。信号的参数,一般就是你定义的属性。
class QQuickText : public QQuickImplicitSizeItem
{
Q_OBJECT
Q_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:
enum HAlignment { AlignLeft = Qt::AlignLeft,
AlignRight = Qt::AlignRight,
AlignHCenter = Qt::AlignHCenter,
AlignJustify = Qt::AlignJustify };
...
QString text() const;
void setText(const QString &); QFont font() const;
void setFont(const QFont &font); QColor color() const;
void setColor(const QColor &c);
...
};

  1. 实现 c++类 (define好了类,之后实现各函数)

  2. 注册 QML 类型 (下一步)

要注册一个 QML 类型,有多种方法可用,如

qmlRegisterSingletonType() 用来注册一个单例类型, 

qmlRegisterType() 注册一个非单例的类型, // 模板函数

qmlRegisterTypeNotAvailable() 注册一个类型用来占位, 

qmlRegisterUncreatableType() 通常用来注册一个具有附加属性的附加类

其中一个原型:

template<typename T>  

// 包名,主版本,次版本,类名
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QtQml>
#include "colorMaker.h" int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);    // 注册qml类型
qmlRegisterType<ColorMaker>("an.qt.ColorMaker", , , "ColorMaker"); QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/colorMaker/main.qml"));
viewer.showExpanded(); return app.exec();
}
import QtQuick 2.0
import QtQuick.Controls 1.1
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: {
colorMaker.start();
}
}
Button {
id: stop;
text: "stop";
anchors.left: start.right;
anchors.leftMargin: ;
anchors.bottom: start.bottom;
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: start.bottom;
onClicked: {
var algorithm = (colorMaker.algorithm() + ) % ;
changeAlgorithm(colorAlgorithm, algorithm);
colorMaker.setAlgorithm(algorithm);
}
} Button {
id: quit;
text: "quit";
anchors.left: colorAlgorithm.right;
anchors.leftMargin: ;
anchors.bottom: start.bottom;
onClicked: {
Qt.quit();
}
} Component.onCompleted: {
colorMaker.color = Qt.rgba(,,, );
colorMaker.setAlgorithm(ColorMaker.LinearIncrease);
changeAlgorithm(colorAlgorithm, colorMaker.algorithm());
} Connections {
target: colorMaker;
onCurrentTime:{
timeLabel.text = strTime;
timeLabel.color = colorMaker.timeColor;
}
} Connections {
target: colorMaker;
onColorChanged:{
colorRect.color = color;
}
}
}

qml中调用c++


  1. 实现 c++类

  2. 注册 QML 类型

  3. 在 QML 中导入类型  ( 下一步 )

将 对象 直接作为参数 传入 QML

把 C++ 中创建的对象作为属性传递到 QML 环境中,然后在 QML 环境中访问。就不需要 import 语句了!

将一个对象注册为属性:

#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QtQml>
#include "colorMaker.h" int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer;

   // viewer.rootContext() 返回的是 QQmlContext 对象。
   // QQmlContext 类代表一个 QML 上下文,它的 setContextProperty() 方法可以为该上下文设置一个全局可见的属性。
viewer.rootContext()->setContextProperty("colorMaker", new ColorMaker); // 从堆上分配了一个 ColorMaker 对象 viewer.setMainQmlFile(QStringLiteral("qml/colorMaker/main.qml"));
viewer.showExpanded(); return app.exec();
}

貌似,这个方法比较方便呐。

import QtQuick 2.0
import QtQuick.Controls 1.1
//[1]
//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: ;
}
/* [2]
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: {
colorMaker.start();
}
}
Button {
id: stop;
text: "stop";
anchors.left: start.right;
anchors.leftMargin: ;
anchors.bottom: start.bottom;
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: start.bottom;
onClicked: {
var algorithm = (colorMaker.algorithm() + ) % ;
changeAlgorithm(colorAlgorithm, algorithm);
colorMaker.setAlgorithm(algorithm);
}
} Button {
id: quit;
text: "quit";
anchors.left: colorAlgorithm.right;
anchors.leftMargin: ;
anchors.bottom: start.bottom;
onClicked: {
Qt.quit();
}
} Component.onCompleted: {
colorMaker.color = Qt.rgba(,,, );
//[3]
//colorMaker.setAlgorithm(ColorMaker.LinearIncrease);
colorMaker.setAlgorithm();
changeAlgorithm(colorAlgorithm, colorMaker.algorithm());
} Connections {
target: colorMaker;
onCurrentTime:{
timeLabel.text = strTime;
timeLabel.color = colorMaker.timeColor;
}
} Connections {
target: colorMaker;
onColorChanged:{
colorRect.color = color;
}
}
}

对象作为参数


二、在c++中使用 QML 对象

 
我们可以使用 QML 对象的信号、槽,访问它们的属性,都没有问题,因为很多 QML 对象对应的类型,原本就是 C++ 类型,比如
    • Image 对应 QQuickImage ,
    • Text 对应 QQuickText
但是,这些与 QML 类型对应的 C++ 类型都是私有的,你写的 C++ 代码也不能直接访问。怎么办?
 
Qt 最核心的一个基础特性,就是元对象系统。
通过元对象系统,你可以查询 QObject 的某个派生类的类名、有哪些信号、槽、属性、可调用方法等等信息
然后也可以使用 QMetaObject::invokeMethod() 调用 QObject 的某个注册到元对象系统中的方法。
而对于使用 Q_PROPERTY 定义的属性,可以使用 QObject 的 property() 方法访问属性,如果该属性定义了 WRITE 方法,还可以使用 setProperty() 修改属性。
 
所以只要我们找到 QML 环境中的某个对象,就可以通过元对象系统来访问它的属性、信号、槽等。
关键就是:查找对象!
 
查找如下QML的对象:
import QtQuick 2.0
import QtQuick.Controls 1.1 Rectangle {
objectName: "rootRect";
width: ;
height: ;
Text {
objectName: "textLabel";
text: "Hello World";
anchors.centerIn: parent;
font.pixelSize: ;
} Button {
anchors.right: parent.right;
anchors.rightMargin: ;
anchors.bottom: parent.bottom;
anchors.bottomMargin: ;
text: "quit";
objectName: "quitButton";
}
}
我们给根元素起了个名字 "rootRect" ,给退出按钮起了个名字 "quitButton" ,给文本起了名字 "textLabel" 。
我们会在 C++ 代码中通过这些个名字来查找对应的对象并改变它们。
 
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QQuickItem>
#include "changeColor.h"
#include <QMetaObject>
#include <QDebug>
#include <QColor>
#include <QVariant> int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/callQml/main.qml"));
viewer.showExpanded(); QQuickItem * rootItem = viewer.rootObject();
new ChangeQmlColor(rootItem);  // 内部通过一个定时器,一秒改变一次传入对象的颜色
QObject * quitButton = rootItem->findChild<QObject*>("quitButton");
if(quitButton)
{
      // clicked() 信号连接到 QGuiApplication 的 quit() 槽上
QObject::connect(quitButton, SIGNAL(clicked()), &app, SLOT(quit()));
} QObject *textLabel = rootItem->findChild<QObject*>("textLabel");
if(textLabel)
{
//1. failed call
bool bRet = QMetaObject::invokeMethod(textLabel, "setText", Q_ARG(QString, "world hello"));
qDebug() << "call setText return - " << bRet;
textLabel->setProperty("color", QColor::fromRgb(,,));
//2. good call
bRet = QMetaObject::invokeMethod(textLabel, "doLayout"); // 对应的c++中的接口 名词不同,所以上面的失败了
qDebug() << "call doLayout return - " << bRet;
} return app.exec();
}
#ifndef CHANGECOLOR_H
#define CHANGECOLOR_H
#include <QObject>
#include <QTimer> class ChangeQmlColor : public QObject
{
Q_OBJECT
public:
ChangeQmlColor(QObject *target, QObject *parent = );
~ChangeQmlColor(); protected slots:
void onTimeout(); private:
QTimer m_timer;
QObject *m_target;
}; #endif

ChangeQmlColor定义

#include "changeColor.h"
#include <QDateTime>
#include <QColor>
#include <QVariant> ChangeQmlColor::ChangeQmlColor(QObject *target, QObject *parent)
: QObject(parent)
, m_timer(this)
, m_target(target)
{
qsrand(QDateTime::currentDateTime().toTime_t());
connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
m_timer.start();
} ChangeQmlColor::~ChangeQmlColor()
{} void ChangeQmlColor::onTimeout()
{
QColor color = QColor::fromRgb(qrand()%, qrand()%, qrand()%);
m_target->setProperty("color", color);
}

ChangeQmlColor实现

[Qt5] How to connect c++ with QML的更多相关文章

  1. Qt5官方demo分析集29——Extending QML - Property Value Source Example

    此系列的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集28--Extend ...

  2. Qt5官方demo解析集30——Extending QML - Binding Example

    本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集29--Extendin ...

  3. Qt5官方demo解析集28——Extending QML - Signal Support Example

    本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集27--Extendin ...

  4. C语言 C++1X STL QT免费视频课程 QT5界面开发美化 式样表 QML

    C/C++/QT界面开发界面美化视频课程系列 课程1   C语言 C++1X STL QT免费视频课程 QT5界面开发美化 式样表 QML 返回顶部 课程1   C语言 C++1X STL QT免费视 ...

  5. Qt5官方demo解析集21——Extending QML - Adding Types Example

    本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 又是一个新的系列了,只是这个系列和我们之前的Chapt ...

  6. [Code::Blocks] Install wxWidgets & openCV

    The open source, cross platform, free C++ IDE. Code::Blocks is a free C++ IDE built to meet the most ...

  7. 本人SW知识体系导航 - Programming menu

    将感悟心得记于此,重启程序员模式. js, py, c++, java, php 融汇之全栈系列 [Full-stack] 快速上手开发 - React [Full-stack] 状态管理技巧 - R ...

  8. qt5 connect问题

    参考资料:Qt学习之路2     在qt从4到5的升级过程中,connect的方法只是添加了一些重载的形式,qt5新增的connect添加了编译器类型检查,如果遇到匹配失败的,或者找不到信号/槽的地方 ...

  9. QML与C++混合编程详解(转)

    原文转自:http://blog.csdn.net/ieearth/article/details/42243553 原文转自:https://www.cnblogs.com/findumars/p/ ...

随机推荐

  1. poj 1806 分块模拟

    Manhattan 2025 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1318   Accepted: 703 Des ...

  2. Windows Server 2008 系统设置集合

    1.禁用IPV6 netsh interface teredo set state disabled netsh interface 6to4 set state disabled netsh int ...

  3. SQL Server选取本周或上一周数据

    有关SQL Server中有关周的数据查询主要思路来自下面这个语句 select getdate(), dateadd(wk, datediff(wk, 0, DateAdd(Day,-1,getda ...

  4. HTML5+flash打造兼容各浏览器的文件上传方案

    上一篇文章介绍了HTML5版的文件上传插件,相比flash,采用HTML5的新技术无疑可以提升程序的加载速度.但是在目前的情况看来,HTML5的特性支持度不高,插件的可用性范围确实比较窄.例如,我在插 ...

  5. 基于java的设计模式入门(1)——为什么要学习设计模式

    大年初一,楼主在这里给大家拜年,祝大家码上升职加薪,码上有对象结婚,码上有车有房,幸福安康. 过完年,回学校注册报道之后,大概就要回深圳到公司开始实习了.提高自己,无非就有两种方式,一是看书学习,二是 ...

  6. [安卓] 12、开源一个基于SurfaceView的飞行射击类小游戏

    前言  这款安卓小游戏是基于SurfaceView的飞行射击类游戏,采用Java来写,没有采用游戏引擎,注释详细,条理比较清晰,适合初学者了解游戏状态转化自动机和一些继承与封装的技巧. 效果展示    ...

  7. 关于node.js的误会

    昨天写了篇博客,介绍了一下我对node.js的第一次亲密接触后的感受,以为node.js很小众,出乎我意料很多人感兴趣,并且对博客中的细节问题做了评论,最多的是围绕node.js的异步与单线程展开的, ...

  8. Senparc.Weixin.MP SDK 微信公众平台开发教程(十二):OAuth2.0说明

    紧接上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明>,这里专讲OAuth2.0. 理解OAuth2.0 首先我们通过一张图片来了解一下OAu ...

  9. easy-ui JOB 及 小记录

    $:获取  $.ajax({             type: "POST" ,             url: "" ,             cont ...

  10. java 堆栈分析2

    有了mat.同时我们发现Java有提供jvisualvm, jvisualvm是一个不错的工具: heap dump . thread dump. cpu/mem profile 无所不能. 不过观察 ...