C++&QML混合编程官方案例(一)
该系列文章为QT自带案例Writing QML Extensions with C++ 的中文翻译。下面为正文
Chapter 1: Creating a New Type (章节一:创建一个新的类型)
extending-qml/chapter1-basics
扩展QML时的一个常见任务是提供一个新的QML类型,该类型支持内置Qt Quick Type 所提供的功能之外的一些自定义功能。例如,可以这样做来实现特定的数据模型,或者提供具有自定义绘制和绘制功能的类型,或者访问无法通过内置QML功能访问的系统功能(如网络编程)。
在这个教程中,我们将展示如何利用C++的类在Qt Quick module 中 扩展QML的。最终成果将是一个简单的饼图显示,它由多个自定义QML类型实现,这些类型通过绑定和信号等QML特性连接在一起,并以插件的方式在QML中运行。
首先,让我们创建一个名为“piechart”的新QML类型,它有两个属性:name和color。我们将使其在名为“Charts”的可导入类型命名空间中可用,版本为1.0。
我们希望pieChart在qml中呈现出如下代码:
import Charts 1.0
PieChart {
width: 100; height: 100
name: "A simple pie chart"
color: "red"
}
做到这点,我们需要C++的类 封装 PieChart类型和他的两个成员变量,且由于QML广泛使用了Qt的元对象系统,因此这个新类必须:
- 从QObject继承。
- 使用Q_PROPERTY宏声明其属性。
piechart.h
#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)
public:
PieChart(QQuickItem *parent = 0);
QString name() const;
void setName(const QString &name);
QColor color() const;
void setColor(const QColor &color);
void paint(QPainter *painter);
private:
QString m_name;
QColor m_color;
};
这个类 继承自 QQuickPaintedItem 因为我们希望在使用QPainter API执行绘制操作时重写QQuickPaintedItem::Paint()。如果类只是表示某种数据类型,并且不是实际需要显示的项,那么它可以简单地从QObject继承。或者,如果我们想要扩展现有的基于QObject的类的功能,它可以从该类继承。或者,如果我们想要创建一个不需要使用QPainter API执行绘图操作的可视项目,我们可以只创建QQuickItem的子类。
PieCht类使用Q_PROPERTY宏定义两个属性(name和color),并覆盖QQuickPaintedItem::Paint()。Cpp中的类实现只根据需要设置并返回m_name和m_color值,并实现paint()来绘制一个简单的饼图。它还会关闭QGraphicsItem::ItemHasNoContents标志以启用绘制:
PieChart::PieChart(QQuickItem *parent)
: QQuickPaintedItem(parent)
{
}
...
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);
}
现在我们已经定义了Piehart类型,我们将在QML中使用它。App.qml文件创建一个PieChart项,并使用标准QML文本项显示饼图的详细信息:
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
}
}
值得注意的是,尽管color在QML中指定为字符串,但它会自动转换为PieChart颜色属性的QColor对象。为各种其他基本类型提供了自动转换;例如,类似“640x480”的字符串可以自动转换为QSize值。
我们还将创建一个C++应用程序,它使用QQuickView来运行和显示app.qml。应用程序必须使用qmlRegisterType()函数注册piechart类型,才能从QML使用它。如果不注册该类型,app.qml将无法创建一个 PieChart对象。
下面是应用程序main.cpp:
#include <QtQuick/QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<PieChart>("Charts", 1, 0, "PieChart");
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:///app.qml"));
view.show();
return app.exec();
}
这个对qmlRegisterType()的调用在名为“Charts”的类型命名空间中将PieChart类型注册为名为“Piehart”的类型,版本为1.0。
关于qmlRegisterType()函数
这是一个重载函数。
此模板函数在QML系统中注册C++类型。无法从QML系统创建此类型的实例。
当类型不会被名称引用时,应使用此函数。具体地说,它必须用于用作属性绑定左侧的C++类型。
最后,我们编写一个.pro项目文件,其中包含这些文件和声明性库:
QT += qml quick
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
qml.files = *.qml
qml.path = $$DESTPATH
INSTALLS += target qml
现在我们得到如下图: