前言
在Qt环境下QtQuick的编程中会不可避免地涉及到C++和QML之间的交互,QML是一种类似Java Script的语言,使用QML设计的UI比起传统的Qt要时髦得多,因此目前也成为Qt开发的首选。本文主要记录下前两天在Qt开发中使用到的C++和QML交互的部分,当然也是最基本的用法,仅作为一点积累。具体可参考Qt Quick 之 QML 与 C++ 混合编程详解。
C++&QML交互
在QtQuick的编程中,可直接用Qt封装好的QML控件完成UI的设计和控制逻辑,不过在实际开发中往往需要添加一部分自定义的控件,这时可以新建一个继承自QQuickItem
和QQuickPaintedItem
等基类的C++类,通过实现一些接口,使得在QML UI的设计中可以调用此C++对象作为自定义控件使用。通过Qt的元对象系统,C++和QML对象之间可以互相访问对方的信号(signals)、槽(slots)和属性,使得C++和QML的混合编程足够灵活多变,能满足复杂应用程序的开发需求。
Q_OBJECT
Qt中新建的C++类要想使用信号和槽函数机制,必须在类的声明中添加Q_OBJECT宏修饰,例如下面的代码:
#include <QObject>
class myObject: public QObject
{
Q_OBJECT
public:
explicit myObject(QObject *parent = nullptr);
public slots:
signals:
};
Q_PROPERTY
要想在QML中访问C++类的属性,需要使用Q_PROPERTY宏修饰该C++类的属性如下:
#include <QQuickItem>
class myItem: public QQuickItem
{
Q_OBJECT
Q_PROPERTY(int height READ getHeight WRITE setHeight)
Q_PROPERTY(int width READ getWidth WRITE setWidth)
public:
myItem(QQuickItem *parent = nullptr);
inline void setHeight(int height) {
mHeight = height;
}
inline int getHeight() {
return mHeight;
}
inline void setWidth(int width) {
mWidth = width;
}
inline int getWidth() {
return mWidth;
}
public slots:
signals:
private:
int mHeight;
int mWidth;
};
通过上面的Q_PROPERTY宏修饰,在QML中可访问myItem类的mHeight和mWidth属性。注意在访问时使用的是注册的height和width而不是实际的类属性名,两者之间通过setHeight与getHeight和setWidth与getWidth接口函数传递数值。
Q_INVOKABLE
使用Q_INVOKABLE宏修饰的C++类的函数可以在QML中调用,具体的使用方法如下:
#include <QObject>
class myObject: public QObject
{
Q_OBJECT
public:
myObject(QObject *parent = 0);
Q_INVOKABLE void printInfo();
public slots:
signals:
};
注意Q_INVOKABLE宏必须在函数返回类型的前面。
注册C++类到QML
上面写好的C++类可通过qmlRegisterType函数注册为QML可使用的类,函数的定义如下:
inline int qmlRegisterType(
const QUrl &url,
const char *uri,
int versionMajor,
int versionMinor,
const char *qmlName
)
例如要注册一个名为MyObject
的C++类,那么对应的代码如下:
qmlRegisterType<MyObject>("MyObject", 1, 0, "MyObject");
注册后即可在.qml文件中引进使用,引进的方法如下:
import MyObject 1.0
结语
很久没使用Qt编程了,Qt的UI设计也已经从Widget逐步过渡到了QtQuick,不过好在代码迁移没有太大难度,开发者在很短时间内就能享受QML带来的好处。我最早接触C++应用程序开发还是MFC。说实话,MFC相比起Qt确实要复杂很多,之前编写一个MFC的桌面应用经常让我头大,但编写Qt就很少有这种感觉,有时候反而觉得很惬意。。可能这也是为什么现在没人用MFC的原因吧。