Qt5官方demo解析集30——Extending QML - Binding Example
本系列全部文章能够在这里查看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的更多相关文章
- Qt5官方demo解析集28——Extending QML - Signal Support Example
本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集27--Extendin ...
- Qt5官方demo解析集21——Extending QML - Adding Types Example
本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 又是一个新的系列了,只是这个系列和我们之前的Chapt ...
- Qt5官方demo分析集29——Extending QML - Property Value Source Example
此系列的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集28--Extend ...
- Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles
本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文 Qt5官方demo解析集12--Qt Quic ...
- Qt5官方demo解析集35——Music Player(使用winextras模块)
本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集34——Concentr ...
- Qt5官方demo解析集(36个)
http://blog.csdn.net/cloud_castle/article/category/2123873 http://blog.csdn.net/cloud_castle/article ...
- Qt5官方demo分析集11——Qt Quick Particles Examples - Affectors
在这个系列中的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集10--Qt ...
- Qt5官方demo分析集10——Qt Quick Particles Examples - Emitters
此系列的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 前段时间去听了Qt在北京的开发人员大会,感觉QML ...
- 订餐系统之微信支付,踩了官方demo的坑
最近一个项目要增加微信支付的功能,想来这个东西出来这么久了,按微信提供的应该可以很快搞定的,结果提供的demo( JS API网页支付)中各种坑,咨询他们的客服,态度倒是非常好,就是解决不了问 ...
随机推荐
- windows 使用git上传代码至github
1. 首先创建github账户 2. 创建github项目 3. windows安装git工具 ·下载地址:https://git-for-windows.github.io/ ,下载直接安装即可, ...
- docker系列之网络配置
docker 网络配置 docker 安装后, 会自动在系统做一个网桥配置 docker0 . 其容器都会分配到此网桥配置下的独立, 私有 IP 地址. 如果你要自己配置桥接, 也可以把 docker ...
- Python对Dict排序
对下面的Dict: aps = {} for key in T.keys(): ap = average_precision(T[key], P[key]) aps[key] = ap 如果用valu ...
- pytorch导入错误so: undefined symbol: _Z11libshm_initPKc
首先删除torch文件 或者直接卸载 删除会更彻底 https://blog.csdn.net/qq_37674858/article/details/88870124 但是会发现卸载重装pytorc ...
- 项目之socket
客户端socket 客户端套接字完成的任务很统一,发送请求,接收请求结果 可以封装成一个方法 使用的tcp协议存在粘包问题,故需要自定义报头 import json import struct #项目 ...
- Lex与Yacc学习(九)之Yacc语法
Yacc语法 本文讨论yacc语法的格式并描述可用的各种特征和选项 yacc语法结构 yacc语法包括三部分:定义段.规则段和用户子例程段 ...定义段... %% ...规则段... %% ...用 ...
- 通过 PC 远程控制 Android 的应用 -- 可以将手机屏幕投射显示到电脑上
测试结果中的部分测试图:Mobizen手机界面: 电脑界面: 主界面 视频 全屏视频 WebKey手机界面: 电脑界面: AirMore手机界面: 电脑界面:主界面 镜像 全屏镜像 Airdroid手 ...
- 关于Linux下安装Oracle
参考文档:http://www.cnblogs.com/gaojun/archive/2012/11/22/2783257.html 中文字符集设置: http://blog.csdn.net/ ...
- 【01】markdown特殊说明
[01]说明 Markdown 的目标是实现「易读易写」. 可读性,无论如何,都是最重要的.一份使用 Markdown 格式撰写的文件应该可以直接以纯文本发布,并且看起来不会像是由许多标签或是格式指令 ...
- 面试准备——java设计模式
1 总体来说,设计模式分为三大类: 设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案. 创建型模式(五种):工厂方法模式.抽象工厂模式.单例模式. ...