[Qt5] How to connect c++ with QML
Qt5处于过度阶段,架构繁琐,学习成本不低。尤其是UI代码竟然被重写,变了天。
Qt中的c++可能是连接OPENCV与QML的一个不错的桥梁,在此学习这部分实用的技术。
Reference: http://blog.csdn.net/foruok/article/details/32698603
一、在 QML 中调用 c++
实现 c++类
注册 QML 类型
在 QML 中导入类型
在 QML 创建由 C++ 导出的类型的实例并使用
Qt 提供了两种在 QML 环境中使用 C++ 对象的方式:
- 在 C++ 中实现一个类,注册到 QML 环境中, QML 环境中使用该类型创建对象
- 在 C++ 中构造一个对象,将这个对象设置为 QML 的上下文属性,在 QML 环境中直接使用改属性
对要导出的 C++ 类都有要求,不是一个类的所有方法、变量都可以被 QML 使用。
因此我们先来看看怎样让一个方法或属性可以被 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 标记 如果你没有为属性指定 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);
...
};
实现 c++类 (define好了类,之后实现各函数)
注册 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++
实现 c++类
注册 QML 类型
在 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 对象
- Image 对应 QQuickImage ,
- Text 对应 QQuickText
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";
}
}
#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的更多相关文章
- Qt5官方demo分析集29——Extending QML - Property Value Source Example
此系列的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集28--Extend ...
- Qt5官方demo解析集30——Extending QML - Binding Example
本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集29--Extendin ...
- Qt5官方demo解析集28——Extending QML - Signal Support Example
本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集27--Extendin ...
- C语言 C++1X STL QT免费视频课程 QT5界面开发美化 式样表 QML
C/C++/QT界面开发界面美化视频课程系列 课程1 C语言 C++1X STL QT免费视频课程 QT5界面开发美化 式样表 QML 返回顶部 课程1 C语言 C++1X STL QT免费视 ...
- Qt5官方demo解析集21——Extending QML - Adding Types Example
本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 又是一个新的系列了,只是这个系列和我们之前的Chapt ...
- [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 ...
- 本人SW知识体系导航 - Programming menu
将感悟心得记于此,重启程序员模式. js, py, c++, java, php 融汇之全栈系列 [Full-stack] 快速上手开发 - React [Full-stack] 状态管理技巧 - R ...
- qt5 connect问题
参考资料:Qt学习之路2 在qt从4到5的升级过程中,connect的方法只是添加了一些重载的形式,qt5新增的connect添加了编译器类型检查,如果遇到匹配失败的,或者找不到信号/槽的地方 ...
- QML与C++混合编程详解(转)
原文转自:http://blog.csdn.net/ieearth/article/details/42243553 原文转自:https://www.cnblogs.com/findumars/p/ ...
随机推荐
- poj 1806 分块模拟
Manhattan 2025 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 1318 Accepted: 703 Des ...
- Windows Server 2008 系统设置集合
1.禁用IPV6 netsh interface teredo set state disabled netsh interface 6to4 set state disabled netsh int ...
- SQL Server选取本周或上一周数据
有关SQL Server中有关周的数据查询主要思路来自下面这个语句 select getdate(), dateadd(wk, datediff(wk, 0, DateAdd(Day,-1,getda ...
- HTML5+flash打造兼容各浏览器的文件上传方案
上一篇文章介绍了HTML5版的文件上传插件,相比flash,采用HTML5的新技术无疑可以提升程序的加载速度.但是在目前的情况看来,HTML5的特性支持度不高,插件的可用性范围确实比较窄.例如,我在插 ...
- 基于java的设计模式入门(1)——为什么要学习设计模式
大年初一,楼主在这里给大家拜年,祝大家码上升职加薪,码上有对象结婚,码上有车有房,幸福安康. 过完年,回学校注册报道之后,大概就要回深圳到公司开始实习了.提高自己,无非就有两种方式,一是看书学习,二是 ...
- [安卓] 12、开源一个基于SurfaceView的飞行射击类小游戏
前言 这款安卓小游戏是基于SurfaceView的飞行射击类游戏,采用Java来写,没有采用游戏引擎,注释详细,条理比较清晰,适合初学者了解游戏状态转化自动机和一些继承与封装的技巧. 效果展示 ...
- 关于node.js的误会
昨天写了篇博客,介绍了一下我对node.js的第一次亲密接触后的感受,以为node.js很小众,出乎我意料很多人感兴趣,并且对博客中的细节问题做了评论,最多的是围绕node.js的异步与单线程展开的, ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十二):OAuth2.0说明
紧接上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明>,这里专讲OAuth2.0. 理解OAuth2.0 首先我们通过一张图片来了解一下OAu ...
- easy-ui JOB 及 小记录
$:获取 $.ajax({ type: "POST" , url: "" , cont ...
- java 堆栈分析2
有了mat.同时我们发现Java有提供jvisualvm, jvisualvm是一个不错的工具: heap dump . thread dump. cpu/mem profile 无所不能. 不过观察 ...