参考文档:https://doc.qt.io/qt-6/qtqml-cppintegration-exposecppattributes.html
注册可实例化的类型
先看一个例子,这个例子参考了这个文档:https://doc.qt.io/qt-6/qtqml-cppintegration-definetypes.html#registering-c-types-with-the-qml-type-system
- 定义C++类型
#ifndef MESAGE_H
#define MESAGE_H
#include <QObject>
#include <QtQml/qqmlregistration.h>
class Message : public QObject
{
Q_OBJECT
Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
// 导出的类名
QML_NAMED_ELEMENT(MyMessage)
public:
explicit Message(QObject *parent = nullptr);
QString author(){
return m_author;
}
void setAuthor(QString author)
{
m_author = author;
emit authorChanged(m_author);
}
signals:
void authorChanged(QString author);
private:
QString m_author = "hello world";
};
#endif // MESAGE_H
- 配置.pro文件
CONFIG += qmltypes
QML_IMPORT_NAME = an.qt.messaging
QML_IMPORT_MAJOR_VERSION = 1
INCLUDEPATH += an/qt/messaging
编译工程,编译时有一个警告,忽略它...
- 在QML文件中使用
import QtQuick
import QtQuick.Controls
import an.qt.messaging 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
Text {
text: msg.author
}
}
property int count: 0
MyMessage {
id: msg
author: "author"
onAuthorChanged: console.log("changed")
}
Button {
x: 22
y: 100
text: "Button"
onClicked: {
msg.author = "clicked" + count;
count ++
}
}
}
运行结果
小结
- Message 继承自 QObject,并且在类中使用了Q_OBJECT宏
- QML_NAMED_ELEMENT(MyMessage),MyMessage是在QML中可以直接使用的类名
MyMessage {
id: msg
author: "author"
onAuthorChanged: console.log("changed")
}
CONFIG += qmltypes
QML_IMPORT_NAME = an.qt.messaging
QML_IMPORT_MAJOR_VERSION = 1
INCLUDEPATH += an/qt/messaging
CONFIG += qmltypes就认为这是固定语法吧
QML_IMPORT_NAME = an.qt.messaging定义了包名
QML_IMPORT_MAJOR_VERSION = 1 定义的主版本号
import an.qt.messaging 1.0
MyMessage {
id: msg
author: "author"
onAuthorChanged: console.log("changed")
}
教程
官方提供了一个教程示例:https://doc.qt.io/qt-6/qtqml-tutorials-extending-qml-example.html
如运行示例?
在输入框中输入“Writing QML Extensions with C++”
在编辑模式下,展开extending-qml,右选择运行...
Chapter1: 创建新类型
目标:
- 创建一个新类型PieChart,它有一个name和color属性
- 在QML文件中可以这样使用PieChart
import Charts 1.0
PieChart {
width: 100; height: 100
name: "A simple pie chart"
color: "red"
}
实现
定义类型
QML拓展要用到Qt的元对象系统,所以新类(PieChart)必须满足以下条件:
- 继承自 QObject, 并且使用Q_OBJECT宏
- 使用Q_PROPERTY宏声明属性
#include <QtQuick/QQuickPaintedItem>
#include <QColor>
class PieChart : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QColor color READ color WRITE setColor)
QML_ELEMENT
public:
PieChart(QQuickItem *parent = nullptr);
QString name() const;
void setName(const QString &name);
QColor color() const;
void setColor(const QColor &color);
void paint(QPainter *painter) override;
private:
QString m_name;
QColor m_color;
};
PieChart继承自QQuickPaintedItem,继承这个类的目的是重载paint()函数,在这个函数中使用QPainter api执行绘图操作,或者你有别的目的:
- 如果只是简单的数据类型,不需要显示,只需继承自QObject就可以了
- 如果要拓展基于QObject(QObject或它的了类)类型的某个功能,直接用这个类替换即可(这好像是一句废话)
- 如果要创建一个不需执行绘图操作的可见类型,需要继承自QQuickItem
PieChart做了什么事情:
qmake的设置
为了使用注册生效,还需要在项目文件(chapter1-basics.pro)中添加如下配置:
CONFIG += qmltypes
QML_IMPORT_NAME = Charts
QML_IMPORT_MAJOR_VERSION = 1
类的实现
- 设置和获取m_name和m_color的简单实现
- 在paint函数中绘制饼图
#include "piechart.h"
#include <QPainter>
//![0]
PieChart::PieChart(QQuickItem *parent)
: QQuickPaintedItem(parent)
{
}
//![0]
QString PieChart::name() const
{
return m_name;
}
void PieChart::setName(const QString &name)
{
m_name = name;
}
QColor PieChart::color() const
{
return m_color;
}
void PieChart::setColor(const QColor &color)
{
m_color = color;
}
//![1]
void PieChart::paint(QPainter *painter)
{
QPen pen(m_color, 2);
painter->setPen(pen);
painter->setRenderHints(QPainter::Antialiasing, true);
painter->drawPie(boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16);
}
//![1]
在paint函数中用到了QPainter绘制饼形。
第37行中,boundingRect.adjusted(1, 1, -1, -1),四边都向内缩减了1个单位,所在QML中指定width/height时,饼形大小也会跟关改变。
在QML中使用PieChart
import Charts 1.0
import QtQuick 2.0
Item {
width: 300; height: 200
PieChart {
id: aPieChart
anchors.centerIn: parent
width: 100; height: 100
name: "A simple pie chart"
color: "red"
}
Text {
anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
text: aPieChart.name
}
}
注意:第12行color:“red”,字符串red会自动转换成QColor类型,其它基础类型也提供了自动转换的功能,如 “640x480”可以转换成QSize.
关于基础类型:https://doc.qt.io/qt-6/qtqml-typesystem-basictypes.html
在main.cpp中使用QQuickView运行显示app.qml
#include "piechart.h"
#include <QtQuick/QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:///app.qml"));
view.show();
return QGuiApplication::exec();
}
关于QGuiApplication: https://doc.qt.io/qt-6/qguiapplication.html
编译
chapter1-basics.pro内容:
QT += qml quick
CONFIG += qmltypes
QML_IMPORT_NAME = Charts
QML_IMPORT_MAJOR_VERSION = 1
HEADERS += piechart.h
SOURCES += piechart.cpp \
main.cpp
RESOURCES += chapter1-basics.qrc
DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter1-basics
target.path = $$DESTPATH
INSTALLS += target
QT_INSTALL_EXAMPLES的值是什么??
我在这个文档中找到了相关信息:https://doc.qt.io/qt-6/qmake-environment-reference.html
QT_INSTALL_EXAMPLES - location of examples
作为qt程序员,qmake还是有必要了解一下的:https://doc.qt.io/qt-6/qmake-manual.html
结尾
还有5个部分...