生日歌,valuesource

本文探讨了如何在QML中使用C++类,并详细分析了BirthdayParty和HappyBirthdaySong两个示例类的设计与实现过程。介绍了如何通过C++为QML提供更丰富的功能,包括属性绑定、信号槽机制及附加工具属性的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

人分男人和女人,鞋的属性增加了,商标,颜色,价格,尺寸

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

鞋这里当组合对象使用了,在人的内部作为一个属性。

重点看BirthdayPartyHappyBirthdaySong这两个类。

   

class BirthdayParty : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Person *host READ host WRITE setHost)
    Q_PROPERTY(QQmlListProperty<Personguests READ guests)
// ![0]
    Q_PROPERTY(QString announcement READ announcement WRITE setAnnouncement)
// ![0]
    Q_CLASSINFO("DefaultProperty""guests")
public:
    BirthdayParty(QObject *parent = 0);

    Person *host() const;
    void setHost(Person *);

    QQmlListProperty<Personguests();
    int guestCount() const;
    Person *guest(intconst;

    QString announcement() const;
    void setAnnouncement(const QString &);

    static BirthdayPartyAttached *qmlAttachedProperties(QObject *);

    void startParty();
signals:
    void partyStarted(const QTime &time);

private:
    Person *m_host;
    QList<Person *> m_guests;
};

过生日的主人有一个m_host,参加者有多个m_guests,这里Q_CLASSINFO简单说明一下就是给这个类注册一个属性一个值,比如类的作者:wdj,时间:20120511。当然通过元对象是可以获取了。

    再强调一下In QML, the type of a list properties - and the guests property is a list of people - are all of type QQmlListProperty<T>. QQmlListProperty is simple value type that contains a set of function pointers.原文意思所有的属性都是函数指针,看脚本

 host: Boy {
        name: "Bob Jones"
        shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
    }

host:啥意思,(1)BirthdayParty类的一个属性(2)代表BirthdayParty一个函数指针,明白了吧微笑,这个类为qml提供了3个属性(函数指针)host,announcement

QML_DECLARE_TYPEINFO(BirthdayPartyQML_HAS_ATTACHED_PROPERTIES)
这个宏我们应该是配合static BirthdayPartyAttached *qmlAttachedProperties(QObject *);来一起使用,qt帮助有一点点晦涩,开始没看懂,结合上面的例子,我个人觉得就是类似友元定义,(Qt叫Attached Property), BirthdayParty使用 BirthdayPartyAttached 属性(私有信息),呵呵,这样体现C++低耦合,我们就当是一个类去访问他的友元比较容易懂了。


class HappyBirthdaySong : public QObjectpublic QQmlPropertyValueSource
{
    Q_OBJECT
    Q_INTERFACES(QQmlPropertyValueSource)
// ![0]
    Q_PROPERTY(QString name READ name WRITE setName)
// ![1]
public:
    HappyBirthdaySong(QObject *parent = 0);

    virtual void setTarget(const QQmlProperty &);
// ![1]

    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]
};
看这个类首先看看关于 QQmlPropertyValueSource介绍,用过JS,特别是AngularJS库的人知道我们说定义一个属性值,然后再HTML位置指定,当我们JS程序改变这个值的时候,页面自动就刷新了。这个类就是做这个用的,Property Value Sources中对此有介绍,有点晦涩,不过看代码应该能明白。

    HappyBirthdaySong这个类声明是固定的,想用Property Value Sources就得这么继承着写,Q_OBJECT和Q_INTERFACES(QQmlPropertyValueSource)随之写上,没啥好说了,virtual void setTarget(const QQmlProperty &);虚函数必备,在这个类定义了一个定时器,实时去刷新m_target这个值,那么这个值绑定到哪里了呢,看脚本:HappyBirthdaySong on announcement,OK,绑定到了BirthdayParty的announcement了,

void BirthdayParty::setAnnouncement(const QString &speak)
{
    qWarning() << qPrintable(speak);
}
这个属性每次被修改后就调用这个函数, qPrintable等价QString的toLocal8Bit().constData().

整个例子差不多分析完了,看main.cpp,qmlRegisterType将C++类型注册到QML引擎中,这里提一下没有参数的注册,This is an overloaded function.This template function registers the C++ type in the QML system. Instances of this type cannot be created from the QML system.原文在此,一个重载的模板函数,最后一句,这个类型的实例不可以被创建来自于QML系统。我理解是保护的作用,这里所有的人必须用派生类,辨别男女,如果你用一个Person对象的话显然程序凌乱了,这里起到一个保护作用,类型注册进去,但是不允许创建实例(C++中虚基类,单体都是这样)。

    QQmlEngine engine;
    QQmlComponent component(&engineQUrl("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>(guestfalse);
            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();
    }

qmlAttachedPropertiesObject获取那个友元对象,记得前面说的吗?

  这里需要用标准字符看打印信息QTextCodeccodec = QTextCodec::codecForName("UTF-8");可以发现都是中文了。

最后我修正了下脚本:

import People 1.0
import QtQuick 2.0  // For QColor

// ![0]
BirthdayParty {
    HappyBirthdaySong on announcement { name: "Bob Jones" }
// ![0]

    onPartyStarted1: console.log("This party started rockin' at " + time);

    host: Boy {
        name: "Bob Jones"
        shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
    }
	guests:[
		 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]
}

这里需要说明脚本中的槽调用,在C++中定义了PartyStarted1信号,脚本中相应对应的槽就是on+信号名:后面输出响应信息即可。

最后,我觉得把参加人的对象写明确一些适合看代码(红色部分),不然会有些迷惑,原文不写guest,确可以将除host外的person全部划入guest我其实不是很理解,路过的可以留言,大家共同进步吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值