此系列的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873

接上文Qt5官方demo解析集28——Extending
QML - Signal Support Example

我们常常会在QML代码中使用Animation和bindings。以使得我们的程序具有更好的动态性能。那么,类似NumberAnimation这样的QML类似实际上是提供了一个算法来为属性提供动态变化的数值。或者说是提供了一个值的集合。这里Qt将其称作“属性值来源”(Property Value Source),并为这些QML类型提供了一个通用的接口。即QQmlPropertyValueSource。通过继承这个类,我们能够实现自己定义的Property
Value Source。

在前面的项目中加入一个类happybirthdaysong,用来自己定义地控制BirthdayParty中announcement属性的变化:

这个demo向我们展示了这个自己定义的过程。happybirthdaysong.h:

#ifndef HAPPYBIRTHDAYSONG_H
#define HAPPYBIRTHDAYSONG_H #include <QQmlPropertyValueSource>
#include <QQmlProperty>
#include <qqml.h> #include <QStringList> // ![0]
class HappyBirthdaySong : public QObject, public QQmlPropertyValueSource // 因为QQmlPropertyValueSource是一个接口类
{ // 我们还须要继承QObject
Q_OBJECT
Q_INTERFACES(QQmlPropertyValueSource) // 声明接口
// ![0]
Q_PROPERTY(QString name READ name WRITE setName) // name属性用来设置生日歌的对象
// ![1]
public:
HappyBirthdaySong(QObject *parent = 0); virtual void setTarget(const QQmlProperty &); // 用来指明作用的属性对象
// ![1] // <PropertyValueSource> on <property>时被调用 QString name() const; // 自己定义属性的读写函数
void setName(const QString &); private slots:
void advance(); // 更新函数,每秒输出一句歌词 private:
int m_line;
QStringList m_lyrics;
QQmlProperty m_target;
QString m_name;
// ![2]
};
// ![2] #endif // HAPPYBIRTHDAYSONG_H

happybirthdaysong.cpp:

#include "happybirthdaysong.h"
#include <QTimer> HappyBirthdaySong::HappyBirthdaySong(QObject *parent)
: QObject(parent), m_line(-1) // 初始化m_line为-1
{ // 使advance()第一次被调用时输出第一句歌词
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; // 该类型作用于某个属性时,Qt会使用这里的函数
} QString HappyBirthdaySong::name() const
{
return m_name;
} void HappyBirthdaySong::setName(const QString &name) // 初始化歌词。并带上“姓名”參数
{
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 << "";
} void HappyBirthdaySong::advance() // 循环显示的好方式
{
m_line = (m_line + 1) % m_lyrics.count(); m_target.write(m_lyrics.at(m_line));
}

Person类没有变化,而BirthdayParty类则单纯地加入了一个属性announcement来使上面的Source能作用其上,它与其它属性没有不同,类型为QString。用来赋予不同的歌词。

Q_PROPERTY(QString announcement READ announcement WRITE setAnnouncement)

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

最后。这个Source须要通过<PropertyValueSource> on <property>这种语句来调用,

因此在QML文件里加入了HappyBirthdaySongonannouncement{name:"BobJones"},使得这个程序得以循环地为Bob
Jones唱生日快乐歌:

example.qml:

import People 1.0
import QtQuick 2.0 // For QColor // ![0]
BirthdayParty {
HappyBirthdaySong on announcement { name: "Bob Jones" }
// ![0] onPartyStarted: console.log("This party started rockin' at " + time); host: Boy {
name: "Bob Jones"
shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
} 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]

效果例如以下:

版权声明:本文博客原创文章,博客,未经同意,不得转载。

最新文章

  1. Docker on YARN在Hulu的实现
  2. spring官网改版后,如何下载jar包
  3. 开发板通过UART向主机发送数据
  4. SQL Server中的SQL语句优化与效率问题
  5. 4.Spring Web MVC处理请求的流程
  6. Jsp开发自定义标签,自定义标签将字符串转成指定的时间格式显示
  7. Windows7下U盘安装Ubuntu14.04双系统
  8. cmake 学习笔记(二)
  9. django下载文件
  10. 依赖注入之Autofac使用总结
  11. 使用Kubernetes需要注意的一些问题(FAQ of k8s)
  12. IO通信模型(三)多路复用IO
  13. 可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)
  14. jmeter中测试接口
  15. java问题排查工具之一板斧jstack——使用 jstack 定位 java进程CPU过高的问题
  16. The cast to value type &#39;System.Decimal&#39; failed because the materialized value is null. Either the result type&#39;s generic parameter or the query must use a nullable type.
  17. sklearn总览
  18. Android六大基本布局
  19. Jquery编历数组
  20. 数据库Mysql的学习(七)-自定义函数和流程控制

热门文章

  1. JXL组件生成报告错误(两)
  2. ajax跨域请求学习笔记
  3. Leetcode 实施细节 Rotate Image
  4. 好的安排小明(南阳19)(DFS)
  5. HTML5 CSS3 精美案例 : 达到VCD盒个性幻灯片
  6. Cocos2d-x 3.x plist+png 做动画
  7. 【ASP.NET】关于iframe的两个技巧
  8. android user如何打开一个版本号root才干
  9. Spark第一个研究笔记1一片 - Spark一个简短的引论
  10. Android开发学习总结(五)——Android应用目录结构分析(转)