• Qt QML referenceexamples attached Demo hacking


    /*********************************************************************************************
     *                       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", 1,0, "BirthdayParty");
            qmlRegisterType<ShoeDescription>();
            qmlRegisterType<Person>();
            qmlRegisterType<Boy>("People", 1,0, "Boy");
            qmlRegisterType<Girl>("People", 1,0, "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 = 0; 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 0;
        }
    
    二、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 = 0);  //默认构造函数
    
            /**
             * 接下来是一些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 = 0);
    
            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 = 0);
        };
    
        /**
         * 女孩继承自人类
         */
        class Girl : public Person
        {
            Q_OBJECT
        public:
            Girl(QObject * parent = 0);
        };
    
        #endif // PERSON_H
    
    三、person.c
        #include "person.h"
    
        /**
         * 所有的函数都是简单的取值、赋值操作,不解释
         */
    
        ShoeDescription::ShoeDescription(QObject *parent)
        : QObject(parent), m_size(0), m_price(0)
        {
        }
    
        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 = 0);
    
            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(0)
        {
        }
    
        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: 10; color: "black"; brand: "Reebok"; price: 59.95 }
    
                BirthdayParty.rsvp: "2009-07-06"
            }
            // ![1]
            host: Boy {
                name: "Jack Smith"
                shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 }
            }
    
            /**
             * 本人自己添加的额外的代码,用于测试附加属性是否可以放在这里,相当于测试作用域的样子
             */
            BirthdayParty.rsvp: "2015-05-16"
        //! [end]
        }
        //! [end]
  • 相关阅读:
    使用C语言生成任意指定长度的一串随机数
    拷贝ssh公钥到 authorized_keys 后仍然无法免密登录的原因记录
    vs2013 远程调试---笔记
    C++ 根据进程名找到对应Pid
    使用C语言判断一个IP 地址是否为私有地址
    WEB后台传数据给前台
    邮箱跳转
    Cookie记住密码
    Linux服务器攻击防御(转)
    APACHE两种域名跳转法简单完成重定向
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/4511029.html
Copyright © 2020-2023  润新知