All articles in this series can be viewed here in http://blog.csdn.net/cloud_castle/article/category/2123873
Link to qt5 official demo example set 29 -- extending qml-property value source example
Do you still remember that we used to contact qml custom property binding in qt5 official demo release set 17 -- Chapter 3: Adding property bindings? If you do not remember, you can learn more. This example may be better understood due to the project size.
This example is the last example of the extending qml series. Although there are only minor changes compared to the previous example, but let's take a full view of the entire project ~
Binding. qrc is our qml file, which instantiates the birthdayparty class and all its sub-objects.
The person class creates a custom qml type. Since it is not a visualization component and any component of qml is based on the qt meta-Object System, it inherits from qobject.
The shoedescription is defined to describe the shoe attribute of the person class. The shoedescription component does not need to be instantiated when assigning values to shoe.
Then define two Derived classes of person: boy and girl, which can be used to classify person objects.
Person. h:
# Ifndef person_h # define person_h # include <qobject> # include <qcolor> class shoedescription: Public qobject {q_object q_property (INT size read size write setsize policy shoechanged) // notify is used for attribute binding. When the attribute value changes, the shoechanged q_property (qcolor read color write setcolor policy shoechanged) signal is sent, so that the bound property value changes accordingly. q_property (qstring brand read brand write setbrand permission y shoechanged) q_propert Y (qreal price read price write setprice policy shoechanged) Public: shoedescription (qobject * parent = 0); 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); signals: void shoechanged (); // defines the shoechanged () signal PRIVATE: int m_size; qcolor m_color; qstring m_brand; qrea L m_price ;}; class person: Public qobject {q_object q_property (qstring name read name write setname policy namechanged )//! [0] q_property (shoedescription * shoe read shoe constant )//! [0] public: Person (qobject * parent = 0); qstring name () const; void setname (const qstring &); shoedescription * shoe (); signals: void namechanged (); Private: qstring m_name; shoedescription m_shoe;}; class boy: public person {q_objectpublic: Boy (qobject * parent = 0);}; class girl: public person {q_objectpublic: Girl (qobject * parent = 0) ;};# endif // person_h
Person. cpp:
# 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) {If (m_size = s) return; m_size = s; emit shoechanged (); // This signal should be sent after this attribute is correctly written} qcolor shoedescription: color () const {return m_color;} void shoedescription: setcolor (const qcolor & C) {If (m_color = c) return; m_color = C; emit shoechanged ();} qstring shoedescription: Brand () const {return m_brand;} void shoedescription :: setbrand (const qstring & B) {If (m_brand = B) return; m_brand = B; emit shoechanged () ;}qreal shoedescription: price () const {return m_price ;} void shoedescription: setprice (qreal p) {If (m_price = P) return; m_price = P; emit shoechanged ();} person: Person (qobject * parent ): qobject (parent) {} qstring person: Name () const {return m_name;} void person: setname (const qstring & N) {If (m_name = N) return; m_name = N; emit namechanged ();} shoedescription * person: Shoe () {return & m_shoe;} Boy: Boy (qobject * parent): Person (parent) {} GIRL: Girl (qobject * parent): Person (parent ){}
Next is our main class birthdayparty, which is also the root project in example. qml. It has a host attribute with the person pointer as the parameter, which is used to specify the birthday star. There is a guests attribute with the person list pointer as the parameter, which is used to specify the guest and this attribute is set as the default attribute, in this way, the value of the attribute not specified in qml will be assigned to it; an announcement attribute will be dynamically changed to play the lyrics. In addition, this class also defines a partystarted () signal. We can use onpartystarted in qml to respond to this signal.
In addition, a birthdaypartyattached class is defined to provide an additional attribute for the birthdayparty.
Birthdayparty. h:
# Ifndef birthdayparty_h # define birthdayparty_h # include <qobject> # include <qdate> # include <qdebug> # include <qqml. h> # include "person. H "class birthdaypartyattached: Public qobject {q_object q_property (qdate RSVP read RSVP write setrsvp policy rsvpchanged) // in this example, most of the attributes define attribute binding public: birthdaypartyattached (qobject * object); qdate RSVP () const; void setrsvp (const qdate &); signals: void rsvpchanged (); priv Ate: qdate m_rsvp;}; Class birthdayparty: Public qobject {q_object //! [0] q_property (person * Host read host write sethost reset y hostchanged )//! [0] q_property (qqmllistproperty <person> guests read guests) q_property (qstring announcement read announcement write setannouncement) 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; qstring announcement () const; void setannouncement (const qstring &); static variable * qmlattachedproperties (qobject *); void startparty (); signals: void partystarted (const qtime & time); void hostchanged (); Private: person * m_host; qlist <person *> m_guests;}; qml_declare_typeinfo (birthdayparty, birthday) # 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){ if (d != m_rsvp) { m_rsvp = d; emit rsvpChanged(); }}BirthdayParty::BirthdayParty(QObject *parent): QObject(parent), m_host(0){}Person *BirthdayParty::host() const{ return m_host;}void BirthdayParty::setHost(Person *c){ if (c == m_host) return; m_host = c; emit hostChanged();}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);}void BirthdayParty::startParty(){ QTime time = QTime::currentTime(); emit partyStarted(time);}QString BirthdayParty::announcement() const{ return QString();}void BirthdayParty::setAnnouncement(const QString &speak){ qWarning() << qPrintable(speak);}BirthdayPartyAttached *BirthdayParty::qmlAttachedProperties(QObject *object){ return new BirthdayPartyAttached(object);}
In the 9th examples of this series, we came into contact with the happybirthdaysong class, which is a custom property value source that provides the ability to change qml attributes over time, similar to animation. In this example, it is used for the announcement attribute.
Happybirthdaysong. h:
#ifndef HAPPYBIRTHDAYSONG_H#define HAPPYBIRTHDAYSONG_H#include <QQmlPropertyValueSource>#include <QQmlProperty>#include <QStringList>class HappyBirthdaySong : public QObject, public QQmlPropertyValueSource{ Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_INTERFACES(QQmlPropertyValueSource)public: HappyBirthdaySong(QObject *parent = 0); virtual void setTarget(const QQmlProperty &); QString name() const; void setName(const QString &);private slots: void advance();signals: void nameChanged();private: int m_line; QStringList m_lyrics; QQmlProperty m_target; QString m_name;};#endif // HAPPYBIRTHDAYSONG_H
Happybirthdaysong. cpp:
#include "happybirthdaysong.h"#include <QTimer>HappyBirthdaySong::HappyBirthdaySong(QObject *parent): QObject(parent), m_line(-1){ setName(QString()); QTimer *timer = new QTimer(this); QObject::connect(timer, SIGNAL(timeout()), this, SLOT(advance())); timer->start(1000);}void HappyBirthdaySong::setTarget(const QQmlProperty &p){ m_target = p;}QString HappyBirthdaySong::name() const{ return m_name;}void HappyBirthdaySong::setName(const QString &name){ if (m_name == name) return; m_name = name; m_lyrics.clear(); m_lyrics << "Happy birthday to you,"; m_lyrics << "Happy birthday to you,"; m_lyrics << "Happy birthday dear " + m_name + ","; m_lyrics << "Happy birthday to you!"; m_lyrics << ""; emit nameChanged();} void HappyBirthdaySong::advance(){ m_line = (m_line + 1) % m_lyrics.count(); m_target.write(m_lyrics.at(m_line));}
After registering these C ++ classes as the qml type in main. cpp, we can create an instantiated birthdayparty in qml and assign values to its attributes:
Example. qml:
Import people 1.0 import qtquick 2.0 // For qcolor //! [0] birthdayparty {ID: theparty happybirthdaysong on announcement {Name: theparty. host. name} // property bound HOST: Boy {name: "Bob Jones" shoe {size: 12; color: "white"; Brand: "Nike"; price: 90.0 }}//! [0] onpartystarted: console. log ("this party started rockin 'At" + time); boy {name: "Leo Hawkes" birthdayparty. RSVP: "2009-07-06" shoe {size: 10; color: "black"; Brand: "Reebok"; Price: 59.95} Boy {name: "Jack Smith" shoe {size: 8; color: "blue"; Brand: "Puma"; Price: 19.95} girl {name: "Anne Brown" birthdayparty. RSVP: "2009-07-01" shoe. size: 7 shoe. color: "red" shoe. brand: "Marc Jacob "Shoe. Price: 699.99 }//! [1]} //! [1]
Finally, the information of this attribute is called in Main. cpp, and the information is output based on certain rules:
#include <QCoreApplication>#include <QQmlEngine>#include <QQmlComponent>#include <QDebug>#include "birthdayparty.h"#include "happybirthdaysong.h"#include "person.h"int main(int argc, char ** argv){ QCoreApplication app(argc, argv); qmlRegisterType<BirthdayPartyAttached>(); qmlRegisterType<BirthdayParty>("People", 1,0, "BirthdayParty"); qmlRegisterType<HappyBirthdaySong>("People", 1,0, "HappyBirthdaySong"); qmlRegisterType<ShoeDescription>(); qmlRegisterType<Person>(); qmlRegisterType<Boy>("People", 1,0, "Boy"); qmlRegisterType<Girl>("People", 1,0, "Girl"); QQmlEngine engine; 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!"; if (qobject_cast<Boy *>(party->host())) qWarning() << "He is inviting:"; else qWarning() << "She is inviting:"; for (int ii = 0; ii < party->guestCount(); ++ii) { Person *guest = party->guest(ii); QDate rsvpDate; QObject *attached = qmlAttachedPropertiesObject<BirthdayParty>(guest, false); if (attached) rsvpDate = attached->property("rsvp").toDate(); if (rsvpDate.isNull()) qWarning() << " " << guest->name() << "RSVP date: Hasn't RSVP'd"; else qWarning() << " " << guest->name() << "RSVP date:" << qPrintable(rsvpDate.toString()); } party->startParty(); } else { qWarning() << component.errors(); } return app.exec();}
The output is as follows: