A common task when extending QML is to provide a new QML type that supports some custom functionality beyond what is provided by the built-in QML 元素 . For example, this could be done to implement particular data models, or provide elements with custom painting and drawing capabilities, or access system features like network programming that are not accessible through built-in QML features.
In this tutorial, we will show how to use the C++ classes in the Qt Declarative module to extend QML. The end result will be a simple Pie Chart display implemented by several custom QML types connected together through QML features like bindings and signals, and made available to the QML runtime through a plugin.
To begin with, let's create a new QML type called "PieChart" that has two properties: a name and a color. We will make it available in a 模块 called "Charts", with a module version of 1.0.
We want this
PieChart
type to be usable from QML like this:
import Charts 1.0 PieChart { width: 100; height: 100 name: "A simple pie chart" color: "red" }
要做到这,需要 C++ 类封装此
PieChart
type and its two properties. Since QML makes extensive use of Qt's
元对象系统
,此新类必须:
这里是
PieChart
类,定义在
piechart.h
:
#include <QDeclarativeItem> #include <QColor> class PieChart : public QDeclarativeItem { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(QColor color READ color WRITE setColor) public: PieChart(QDeclarativeItem *parent = 0); QString name() const; void setName(const QString &name); QColor color() const; void setColor(const QColor &color); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); private: QString m_name; QColor m_color; };
类继承自 QDeclarativeItem 因为我们想要覆写 QDeclarativeItem::paint () in order to draw. If the class just represented some data type and was not an item that actually needed to be displayed, it could simply inherit from QObject . Or, if we want to extend the functionality of an existing QObject -based class, it could inherit from that class instead.
The
PieChart
类定义了 2 个特性
名称
and
color
,采用
Q_PROPERTY
宏,并覆写
QDeclarativeItem::paint
(). The class implementation in
piechart.cpp
simply sets and returns the
m_name
and
m_color
values as appropriate, and implements
paint()
to draw a simple pie chart. It also turns off the
QGraphicsItem::ItemHasNoContents
flag to enable painting:
PieChart::PieChart(QDeclarativeItem *parent) : QDeclarativeItem(parent) { // need to disable this flag to draw inside a QDeclarativeItem setFlag(QGraphicsItem::ItemHasNoContents, false); } ... void PieChart::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { QPen pen(m_color, 2); painter->setPen(pen); painter->setRenderHints(QPainter::Antialiasing, true); painter->drawPie(boundingRect(), 90 * 16, 290 * 16); }
Now that we have defined the
PieChart
type, we will use it from QML. The
app.qml
file creates a
PieChart
item and display the pie chart's details using a standard QML
Text
item:
import Charts 1.0 import QtQuick 1.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 } }
Notice that although the color is specified as a string in QML, it is automatically converted to a
QColor
object for the PieChart
color
property. Automatic conversions are provided for various other
基本类型
; for example, a string like "640x480" can be automatically converted to a
QSize
值。
We'll also create a C++ application that uses a
QDeclarativeView
to run and display
app.qml
. The application must register the
PieChart
type using the
qmlRegisterType
() function, to allow it to be used from QML. If you don't register the type,
app.qml
won't be able to create a
PieChart
.
这里是应用程序
main.cpp
:
#include "piechart.h" #include <qdeclarative.h> #include <QDeclarativeView> #include <QApplication> int main(int argc, char *argv[]) { QApplication app(argc, argv); qmlRegisterType<PieChart>("Charts", 1, 0, "PieChart"); QDeclarativeView view; view.setSource(QUrl::fromLocalFile("app.qml")); view.show(); return app.exec(); }
This call to
qmlRegisterType
() registers the
PieChart
type as a type called "PieChart", in a module named "Charts", with a module version of 1.0.
Lastly, we write a
.pro
project file that includes the files and the
declarative
库:
QT += declarative
HEADERS += piechart.h
SOURCES += piechart.cpp \
main.cpp
Now we can build and run the application:
Try it yourself with the code in Qt's
examples/tutorials/extending/chapter1-basics
目录。
At the moment, the
app.qml
is run from within a C++ application. This may seem odd if you're used to running QML files with the
QML 查看器
. Later on, we'll show how to create a plugin so that you can run
app.qml
使用
QML 查看器
代替。
文件: