[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/ ...
随机推荐
- mysql客户端导入sql文件命令
mysql -h localhost -u root -p dbname < filename
- AWIT DBackup 0.0.20 发布,备份系统
AWIT DBackup 0.0.20 修复了几个小 bug. AllWorldIT DBackup 是一个备份系统,为每个目录创建一个独立的压缩包,这更便于搜索. 特点: 使用 xz, bzip2, ...
- 从KRE到XRE:ASP.NET 5中正在消失的那些K
前几天写了篇博客ASP.NET 5中的那些K,刚把ASP.NET 5中的那些K搞明白了些,昨天发现微软正在让那些K消失. 首先是在 KRuntime 的git日志中发现的: * Runtime ren ...
- WPF,Silverlight与XAML读书笔记第四十七 - Silverlight与浏览器
说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. 这部分内容主要介绍Silverlight与浏 ...
- mysqlnd cannot connect to MySQL 4.1+
phpMyAdmin - error #2000 - mysqlnd cannot connect to MySQL 4.1+ using the old insecure authenticatio ...
- 怎样记住Integer的最大值(有趣的思维和搞笑的回答)
前言 今天一个同事问我,数据库里面的某表如果用int做PK,那该表最多可以放多少记录,我说简单啊,就是2^31(正数),跟.NET的Int32.MaxValue一样,约等于20亿(正数)吧.同事说,那 ...
- Lucene系列-facet
1.facet的直观认识 facet:面.切面.方面.个人理解就是维度,在满足query的前提下,观察结果在各维度上的分布(一个维度下各子类的数目). 如jd上搜“手机”,得到4009个商品.其中品牌 ...
- 302 Moved Temporarily
这个就是表示 重定向!! 不过,302在不同HTTP协议下的状态信息不同. Moved temporarily (redirect) 你所连接的页面进行了Redirect Found 类似于301,但 ...
- jmx server 和jmx client
启动jmx server 和jmx client,通过jconsole进入jmx server 然后通过其中远程进程,进入jmx client: 发现,两者可用的tab页不同, MBean的数量类型也 ...
- 使用Vue.js时,对Chrome控制台的一点小心得
之前对Chrome控制台的console.log()输出没太放心上,其实仔细研究后,对工作效率有显著的提示.看下面的五段代码: console.log(''); console.log(typeof ...