/*********************************************************************************************
* Qt QML referenceexamples attached Demo hacking
* 说明:
* 1. 本源代码来自Qt自带的Example,而本文也仅仅是代码解读,需要有点基础;
* 2. 由于是Qt自带Demo,分为几个文件,文件存在联系,而本人把所有代码放在这个文件里,会照成阅读困难;
* 3. 由于2中的原因,请尽量在Qt中阅读源程序;
* 4. 强烈建议您使用Qt中的FakeVim进行代码阅读,当然这也只是个建议; :)
*
* 2015-5-17 深圳 晴 南山平山村 曾剑锋
********************************************************************************************/ \\\\\\\\\-*- 目录 -*-/////////
| 一、main.cpp
| 二、person.h
| 三、person.c
| 四、birthdayparty.h
| 五、birthdayparty.cpp
| 六、example.qml
\\\\\\\\\\\\\\\////////////// 一、main.cpp
#include <QCoreApplication>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QDebug>
#include "birthdayparty.h"
#include "person.h" int main(int argc, char ** argv)
{
/**
* The QApplication class manages the GUI application's control flow and main settings.
* 初始化并配置GUI界面环境
*/
QCoreApplication app(argc, argv); /**
* This template function registers the C++ type in the QML system with the name qmlName,
* in the library imported from uri having the version number composed from versionMajor
* and versionMinor.
*
* For example, this registers a C++ class MySliderItem as a QML type named Slider for
* version 1.0 of a type namespace called "com.mycompany.qmlcomponents":
* qmlRegisterType<MySliderItem>("com.mycompany.qmlcomponents", 1, 0, "Slider");
*
* qmlRegisterType<Person>("People", 1,0, "Person"):
* 1. qmlRegisterType是用来向QML系统注册C++类型的;
* 2. 这里相当于向QML系统注册了一个Person 1.0 版本的类;
* 3. 指定了命名空间为Person,所以在qml文件中需要用import People 1.0,引入命名空间,
* 当然这里也制定了版本号;
* 参数说明j:
* 1. 泛型<Person>代表要注册进QML系统C++类;
* 2. 第一个参数是需要创建的QML命名空间;
* 3. 第二、三个参数是对应的QML类型的版本号;
* 4. 第四个参数是C++类对应的QML类型的名字;
*
* 如果注释掉这一行会出现以下错误,编译运行时错误结果:
* QQmlComponent: Component is not ready
* (qrc:example.qml:42:1: module "People" is not installed)
*
*/
qmlRegisterType<BirthdayPartyAttached>();
qmlRegisterType<BirthdayParty>("People", ,, "BirthdayParty");
qmlRegisterType<ShoeDescription>();
qmlRegisterType<Person>();
qmlRegisterType<Boy>("People", ,, "Boy");
qmlRegisterType<Girl>("People", ,, "Girl"); /**
* QQmlApplicationEngine provides a convenient way to load an application from a single QML file.
* 创建QML引擎(engine)
*/
QQmlEngine engine; //QML引擎
/**
* The QQmlComponent class encapsulates a QML component definition Components are reusable,
* encapsulated QML types with well-defined interfaces.
* 个人理解就是加载QML文件的意思,利用component.create()创建对象
*/
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create()); //类型转换获取对象指针 if (party && party->host()) {
qWarning() << party->host()->name() << "is having a birthday!"; //console output /**
* Returns the given object cast to type T if the object is of type T (or of a subclass);
* otherwise returns 0. If object is 0 then it will also return 0.
* 这里相当于类型判断的意思
*/
if (qobject_cast<Boy *>(party->host()))
qWarning() << "He is inviting:";
else
qWarning() << "She is inviting:"; /**
* 这是我自己添加的测试代码,主要用于测试example.qml中的BirthdayParty.rsvp: "2015-05-16"可否写
* 在 BirthdayParty {}里面,测试结果:不一定要写在 Boy {}里面,可以写在任何地方。
*/
/**
* qmlAttachedPropertiesObject: This returns the attached object instance that has been
* attached to the specified attachee by the attaching type T.
*/
QObject *attached_out = qmlAttachedPropertiesObject<BirthdayParty>(party, false);
QDate rsvpDate_out;
if (attached_out)
rsvpDate_out = attached_out->property("rsvp").toDate();
qWarning() << " zjf " << "RSVP date:" << qPrintable(rsvpDate_out.toString()); for (int ii = ; ii < party->guestCount(); ++ii) {
Person *guest = party->guest(ii); //! [query rsvp]
QDate rsvpDate;
/**
* This returns the attached object instance that has been attached to the
* specified attachee by the attaching type T.
*/
QObject *attached = qmlAttachedPropertiesObject<BirthdayParty>(guest, false); if (attached)
rsvpDate = attached->property("rsvp").toDate();
//! [query rsvp]
if (rsvpDate.isNull())
qWarning() << " " << guest->name() << "RSVP date: Hasn't RSVP'd";
else
qWarning() << " " << guest->name() << "RSVP date:" << qPrintable(rsvpDate.toString());
} } else {
qWarning() << component.errors();
} /**
* QStringLiteral: Creating a QString from it is free in this case, and the generated string data
* is stored in the read-only segment of the compiled object file.
* 这是一个宏,用于创建一个字符串,该字符串存放在自读数据区
* QUrl: The most common way to use QUrl is to initialize it via the constructor by passing a QString.
* Otherwise, setUrl() can also be used.
* 最常用于初始化一个QUrl的是给其构造函数传一个字符串,此外也可以使用setUrl()
* engine.load: Loads the root QML file located at filePath:.
* 加载用QML引擎加载要显示的界面
*/
//engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); /**
* Enters the main event loop and waits until exit() is called.
* 进入主事件循环,并等待直到exit()函数被调用
*/
//return app.exec(); return ;
} 二、person.h
#ifndef PERSON_H
#define PERSON_H #include <QObject>
#include <QColor> class ShoeDescription : public QObject
{
/**
* The Q_OBJECT macro must appear in the private section of a class definition
* that declares its own signals and slots or that uses other services provided
* by Qt's meta-object system.
* Q_OBJECT宏应该使用在一个类定义时的私有段,其声明了一些信号和槽
*/
Q_OBJECT /**
* The Property System:
* To declare a property, use the Q_PROPERTY() macro in a class that inherits QObject.
* Q_PROPERTY(type name
* (READ getFunction [WRITE setFunction] |
* MEMBER memberName [(READ getFunction | WRITE setFunction)])
* [RESET resetFunction]
* [NOTIFY notifySignal]
* [REVISION int]
* [DESIGNABLE bool]
* [SCRIPTABLE bool]
* [STORED bool]
* [USER bool]
* [CONSTANT]
* [FINAL])
* 这里采用宏的形式来对变量进行声明定义,由于class默认是私有属性,所以这里我们无法直接
* 访问name、shoeSize,要通过其READ、WRITE函数来进行访问(access)
*/
Q_PROPERTY(int size READ size WRITE setSize)
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(QString brand READ brand WRITE setBrand)
Q_PROPERTY(qreal price READ price WRITE setPrice)
public:
ShoeDescription(QObject *parent = ); //默认构造函数 /**
* 接下来是一些READ、WRITE函数的声明
*/
int size() const;
void setSize(int); QColor color() const;
void setColor(const QColor &); QString brand() const;
void setBrand(const QString &); qreal price() const;
void setPrice(qreal);
private:
int m_size;
QColor m_color;
QString m_brand;
qreal m_price;
}; /**
* 这一部分内容基本在上面已经解释了
*/
class Person : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(ShoeDescription *shoe READ shoe)
public:
Person(QObject *parent = ); QString name() const;
void setName(const QString &); ShoeDescription *shoe();
private:
QString m_name;
ShoeDescription m_shoe;
}; /**
* 男孩继承自人类
*/
class Boy : public Person
{
Q_OBJECT
public:
Boy(QObject * parent = );
}; /**
* 女孩继承自人类
*/
class Girl : public Person
{
Q_OBJECT
public:
Girl(QObject * parent = );
}; #endif // PERSON_H 三、person.c
#include "person.h" /**
* 所有的函数都是简单的取值、赋值操作,不解释
*/ ShoeDescription::ShoeDescription(QObject *parent)
: QObject(parent), m_size(), m_price()
{
} int ShoeDescription::size() const
{
return m_size;
} void ShoeDescription::setSize(int s)
{
m_size = s;
} QColor ShoeDescription::color() const
{
return m_color;
} void ShoeDescription::setColor(const QColor &c)
{
m_color = c;
} QString ShoeDescription::brand() const
{
return m_brand;
} void ShoeDescription::setBrand(const QString &b)
{
m_brand = b;
} qreal ShoeDescription::price() const
{
return m_price;
} void ShoeDescription::setPrice(qreal p)
{
m_price = p;
} Person::Person(QObject *parent)
: QObject(parent)
{
} QString Person::name() const
{
return m_name;
} void Person::setName(const QString &n)
{
m_name = n;
} ShoeDescription *Person::shoe()
{
return &m_shoe;
} Boy::Boy(QObject * parent)
: Person(parent)
{
} Girl::Girl(QObject * parent)
: Person(parent)
{
} 四、birthdayparty.h
#ifndef BIRTHDAYPARTY_H
#define BIRTHDAYPARTY_H #include <QObject>
#include <QDate>
#include <qqml.h>
#include "person.h" // 这一部分内容基本已经在person.h中已经解释了
class BirthdayPartyAttached : public QObject
{
Q_OBJECT
Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp)
public:
BirthdayPartyAttached(QObject *object); QDate rsvp() const;
void setRsvp(const QDate &); private:
QDate m_rsvp;
}; class BirthdayParty : public QObject
{
Q_OBJECT
Q_PROPERTY(Person *host READ host WRITE setHost) /**
* For QMap, QList, and QValueList properties, the property value is a QVariant whose
* value is the entire list or map. Note that the Q_PROPERTY string cannot contain
* commas, because commas separate macro arguments. Therefore, you must use QMap as
* the property type instead of QMap<QString,QVariant>. For consistency, also use
* QList and QValueList instead of QList<QVariant> and QValueList<QVariant>.
*
* 请注意这种写法,
*/
Q_PROPERTY(QQmlListProperty<Person> guests READ guests) /**
* Any QObject-derived type that is registered as an instantiable QML object type
* can optionally specify a default property for the type. A default property is
* the property to which an object's children are automatically assigned if they
* are not assigned to any specific property.
*
* The default property can be set by calling the Q_CLASSINFO() macro for a class
* with a specific "DefaultProperty" value. For example, the MessageBoard class below
* specifies its messages property as the default property for the class:
*
* 将属性guests设为默认属性,这样在QML文件中就可以简写了
*/
Q_CLASSINFO("DefaultProperty", "guests")
public:
BirthdayParty(QObject *parent = ); Person *host() const;
void setHost(Person *); QQmlListProperty<Person> guests();
int guestCount() const;
Person *guest(int) const; //! [static attached]
/**
* The mechanisms for providing attached objects can be implemented from C++ by
* providing classes for the attached object type and attaching type. For the
* attached object type, provide a QObject-derived class that defines the attributes
* to be made accessible to attachee objects. For the attaching type, provide a
* QObject-derived class that.
*
* implements a static qmlAttachedProperties() with the following signature:
*/
static BirthdayPartyAttached *qmlAttachedProperties(QObject *);
//! [static attached]
private:
Person *m_host;
QList<Person *> m_guests;
}; //! [declare attached]
/**
* Declares additional properties of the given Type as described by the specified Flags.
* Current the only supported type info is QML_HAS_ATTACHED_PROPERTIES which declares
* that the Type supports attached properties.
*
* 这里感觉是告诉系统BirthdayParty类附属性,根据example.qml文件里里的写法,
* 附属性写法为BirthdayParty.rsvp
*/
QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES)
//! [declare attached]
#endif // BIRTHDAYPARTY_H 五、birthdayparty.cpp
#include "birthdayparty.h" /**
* 所有的函数都是简单的取值、赋值操作,不解释
*/
BirthdayPartyAttached::BirthdayPartyAttached(QObject *object)
: QObject(object)
{
} QDate BirthdayPartyAttached::rsvp() const
{
return m_rsvp;
} void BirthdayPartyAttached::setRsvp(const QDate &d)
{
m_rsvp = d;
} BirthdayParty::BirthdayParty(QObject *parent)
: QObject(parent), m_host()
{
} Person *BirthdayParty::host() const
{
return m_host;
} void BirthdayParty::setHost(Person *c)
{
m_host = c;
} QQmlListProperty<Person> BirthdayParty::guests()
{
return QQmlListProperty<Person>(this, m_guests);
} int BirthdayParty::guestCount() const
{
return m_guests.count();
} Person *BirthdayParty::guest(int index) const
{
return m_guests.at(index);
} /**
* 实现了attached需要的函数
*/
BirthdayPartyAttached *BirthdayParty::qmlAttachedProperties(QObject *object)
{
return new BirthdayPartyAttached(object);
} 六、example.qml
import People 1.0
import QtQuick 2.0 // For QColor //! [begin]
BirthdayParty {
//! [begin] //! [rsvp]
Boy {
name: "Robert Campbell"
/**
* 这里为什么是这样实现,目前还不是很清楚,但经过测试发现,貌似这就是attach的的意思。
* 另外个人从BirthdayParty.rsvp代表BirthdayParty的附加属性rsvp.
*/
BirthdayParty.rsvp: "2009-07-01"
}
//! [rsvp]
// ![1]
Boy {
name: "Leo Hodges"
shoe { size: ; color: "black"; brand: "Reebok"; price: 59.95 } BirthdayParty.rsvp: "2009-07-06"
}
// ![1]
host: Boy {
name: "Jack Smith"
shoe { size: ; color: "blue"; brand: "Puma"; price: 19.95 }
} /**
* 本人自己添加的额外的代码,用于测试附加属性是否可以放在这里,相当于测试作用域的样子
*/
BirthdayParty.rsvp: "2015-05-16"
//! [end]
}
//! [end]

Qt QML referenceexamples attached Demo hacking的更多相关文章

  1. am335x Qt SocketCAN Demo hacking

    /*********************************************************************************** * am335x Qt Soc ...

  2. Qt qml 单例模式

    Qt qml 单例模式,没什么好说的,看代码吧.单例模式很适合做全局的配置文件. [示例下载] http://download.csdn.net/detail/surfsky/8539313 [以下是 ...

  3. Qt qml listview 列表视图控件(下拉刷新、上拉分页、滚动轴)

    Qt qml listview下拉刷新和上拉分页主要根据contentY来判断.但要加上顶部下拉指示器.滚动条,并封装成可简单调用的组件,着实花了我不少精力:) [先看效果]    [功能] 下拉刷新 ...

  4. qt qml qchart 图表组件

    qt qml qchart 图表组件 * Author: Julien Wintz * Created: Thu Feb 13 23:41:59 2014 (+0100) 这玩意是从chart.js迁 ...

  5. Cmockery macro demo hacking

    /********************************************************************* * Cmockery macro demo hacking ...

  6. Qt 获取usb设备信息 hacking

    /************************************************************************** * Qt 获取usb设备信息 hacking * ...

  7. linux watchdog demo hacking

    /********************************************************************** * linux watchdog demo hackin ...

  8. linux SPI bus demo hacking

    /********************************************************************** * linux SPI bus demo hacking ...

  9. Linux SocketCan client server demo hacking

    /*********************************************************************** * Linux SocketCan client se ...

随机推荐

  1. django字段的参数

    所有的模型字段都可以接收一定数量的参数,比如CharField至少需要一个max_length参数.下面的这些参数是所有字段都可以使用的,并且是可选的. null 该值为True时,Django在数据 ...

  2. [库][c++]tinyxml2使用小结

    参考:http://blog.csdn.net/educast/article/details/12908455 1.配置TinyXML2 去这里把项目弄下来,然后解压,我们之需要里面的tinyxml ...

  3. OpenGL入门程序四:颜色模式

    1.OpenGL支持两种颜色模式: 1>RGBA颜色模式 ,用 glClearColor 指定清空屏幕后的颜色,即“空颜色” . 2>索引颜色模式,用 glClearIndex 指定清空屏 ...

  4. 一个表单里,如果有<button>标签存在,它会自动提交表单

    可以用button代替input type=”submit”吗? 在ie下,<button>标记恐怕还存在几个不大不小的问题. 在一个表单里,如果有一个以上"submit&quo ...

  5. Confluence 6 更新目录

    当编辑目录时候的限制 你不能对你用户属于的目录进行编辑,禁用或者删除.这个能够预防管理员通过修改目录的时候讲自己属于的管理员权限从系统管理员组中删除. 这个限制对所有的用户目录类型适用.例如: 如果当 ...

  6. js下载图片

    DownloadImgZP = imgPath => { const image = new Image(); // 解决跨域 Canvas 污染问题 image.setAttribute('c ...

  7. Python装饰器、生成器、内置函数、json

    这周学习了装饰器和生成器,写下博客,记录一下装饰器和生成器相关的内容. 一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如 ...

  8. VS2013/2015 html 设计视图窗口

  9. XML文档的读、写

    代码: XmlDocument doc = new XmlDocument(); doc.Load("Books.xml"); //1.加载要读取的XML文件 //要想看到数据得先 ...

  10. CentOS 7中firewall防火墙详解和配置以及切换为iptables防火墙

    官方文档介绍地址: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Gui ...