本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873

接上文Qt5官方demo解析集29——Extending
QML - Property Value Source Example

还记得我们以前在Qt5官方demo解析集17——Chapter
3: Adding Property Bindings
一文中接触过QML自己定义类型的属性绑定吗?假设不记得了,能够移步进行了解。由于项目尺寸的原因,那个样例可能更好理解。

这个样例也是我们Extending QML(扩展QML)系列的最后一个样例了,尽管相较前一个样例也仅仅有小小的修改。只是我们还是把整个project都完整的看一遍吧~

binding.qrc中是我们的qml文件,它实例化了BirthdayParty类以及其全部的子对象。

Person类建立了一个自己定义的QML类型,因为它并非一个可视化组件,且QML不论什么组件均基于Qt 的元对象系统,因此继承自QObject。

接着定义了ShoeDescription用来对Person类的shoe属性进行描写叙述,使用特定的方法。我们在对shoe赋值时不须要实例化这个ShoeDescription组件。

再定义两个Person的派生类Boy、Girl,能够用来对Person对象分类。

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 NOTIFY shoeChanged) // NOTIFY用在属性绑定,当该属性值发生改变时发出信号shoeChanged
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY shoeChanged) // 通过该信号,我们就能使得被绑定的属性值随之发生改变
Q_PROPERTY(QString brand READ brand WRITE setBrand NOTIFY shoeChanged)
Q_PROPERTY(qreal price READ price WRITE setPrice NOTIFY 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(); // 定义该shoeChanged()信号 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 NOTIFY 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_OBJECT
public:
Boy(QObject * parent = 0);
}; class Girl : public Person
{
Q_OBJECT
public:
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(); // 该信号应该在该属性被正确写入后发出
} 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)
{
}

接下来是我们的主类BirthdayParty,它也是example.qml中的根项目。它有一个以Person指针为參数的host属性,用来指明寿星;有一个以Person列表指针为參数guests属性,用来指明客人,而且该属性被设置为默认属性,这样在QML中没有指明属性的值将被划归它的名下。一个announcement属性,用来被动态改变以播放歌词。另外,该类还定义了一个partyStarted()信号,我们能够在QML中使用onPartyStarted
来响应该信号。

此外,再定义一个BirthdayPartyAttached类。它用来为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 NOTIFY rsvpChanged) // 该例中大多数属性均定义了属性绑定
public:
BirthdayPartyAttached(QObject *object); QDate rsvp() const;
void setRsvp(const QDate &); signals:
void rsvpChanged(); private:
QDate m_rsvp;
}; class BirthdayParty : public QObject
{
Q_OBJECT
// ![0]
Q_PROPERTY(Person *host READ host WRITE setHost NOTIFY 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 BirthdayPartyAttached *qmlAttachedProperties(QObject *); void startParty();
signals:
void partyStarted(const QTime &time);
void hostChanged(); private:
Person *m_host;
QList<Person *> m_guests;
}; QML_DECLARE_TYPEINFO(BirthdayParty, QML_HAS_ATTACHED_PROPERTIES) #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);
}

在该系列第9个样例中,我们接触到了HappyBirthdaySong类,它是一个自己定义的Property Value Source,用来为QML属性提供随时间变化的能力,类似于Animation。在该样例中,它被用于announcement属性。

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));
}

在main.cpp中将这些C++类注冊成QML类型后。我们就能够在QML中创建一个实例化的BirthdayParty,并对其属性赋值:

example.qml:

import People 1.0
import QtQuick 2.0 // For QColor // ![0]
BirthdayParty {
id: theParty HappyBirthdaySong on announcement { name: theParty.host.name } // 属性绑定 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 Hodges"
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 Jacobs"
shoe.price: 699.99
} // ![1]
}
// ![1]

最后,在main.cpp调用这个属性的信息。并基于一定的规则输出这些信息:

#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();
}

输出例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2xvdWRfY2FzdGxl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

Qt5官方demo解析集30——Extending QML - Binding Example的更多相关文章

  1. Qt5官方demo解析集28——Extending QML - Signal Support Example

    本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集27--Extendin ...

  2. Qt5官方demo解析集21——Extending QML - Adding Types Example

    本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 又是一个新的系列了,只是这个系列和我们之前的Chapt ...

  3. Qt5官方demo分析集29——Extending QML - Property Value Source Example

    此系列的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集28--Extend ...

  4. Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles

    本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文 Qt5官方demo解析集12--Qt Quic ...

  5. Qt5官方demo解析集35——Music Player(使用winextras模块)

    本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集34——Concentr ...

  6. Qt5官方demo解析集(36个)

    http://blog.csdn.net/cloud_castle/article/category/2123873 http://blog.csdn.net/cloud_castle/article ...

  7. Qt5官方demo分析集11——Qt Quick Particles Examples - Affectors

    在这个系列中的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集10--Qt ...

  8. Qt5官方demo分析集10——Qt Quick Particles Examples - Emitters

    此系列的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 前段时间去听了Qt在北京的开发人员大会,感觉QML ...

  9. 订餐系统之微信支付,踩了官方demo的坑

        最近一个项目要增加微信支付的功能,想来这个东西出来这么久了,按微信提供的应该可以很快搞定的,结果提供的demo( JS API网页支付)中各种坑,咨询他们的客服,态度倒是非常好,就是解决不了问 ...

随机推荐

  1. 将find过滤添加到数组

    array=($(find . -name "*.txt"))for i in "${array[@]}"; do echo $i; done

  2. [php] 高级教程

    include 和 require 语句用于在执行流中插入写在其他文件中的有用的代码. include 和 require 除了处理错误的方式不同之外,在其他方面都是相同的: require 生成一个 ...

  3. jq相关操作

    1事件: <div class="ele">123</div> box.onclick = function(ev){ ev:系统传入的事件对象 ele.i ...

  4. 牛客网暑期ACM多校训练营(第六场) C Generation I(组合数学, 逆元)

    中链接: https://www.nowcoder.com/acm/contest/144/C 题意: 给定n个集合, 要求用n次操作, 第i次操作用1~m中一个数填入 i ~ n个集合中, 集合无序 ...

  5. eclipse代码格式化快捷键无法使用

    [产生原因] Ctrl+Shift+F快捷键组合被其他应用占有,如输入法. [解决方案] 关闭或更换其他应用快捷键或更换eclipse对应的快捷键组合.

  6. redis 内存管理与数据淘汰机制(转载)

    原文地址:http://www.jianshu.com/p/2f14bc570563?from=jiantop.com 最大内存设置 默认情况下,在32位OS中,Redis最大使用3GB的内存,在64 ...

  7. css 标题

    纯CSS制作的复古风格的大标题 .vintage{ background: #EEE url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAA ...

  8. win10系统中virtualbox无法安装64位系统

    win10系统中virtualbox无法安装64位系统 先总结下如果想在虚拟机中安装64位的Linux系统,最好能满足这几个条件: 64位CPU 64位操作系统 64位的虚拟机软件 开启BIOS虚拟化 ...

  9. luogu1345 [USACO5.4]奶牛的电信Telecowmunication

    对于每个点,把它拆成有权值为1的边相连的两个点,原边是inf. 边的起点统一加n,ss也加n 这就成了最小割 #include <iostream> #include <cstrin ...

  10. 数据库质疑或只有MDF文件资料

    --允许进行系统表的操作 use master declare @databasename varchar(255) set @databasename='Blwy BarCode' --1.如果用户 ...