扩展QML(高级)- 连接属性#

这是6个教程示例的第五个,使用生日派对为例演示QML的一些高级特性。

现在是主人发送邀请的时候了。为了跟踪哪些客人已回复邀请及其回复时间,我们需要一个地方来存储这些信息。将这些信息存储在BirthdayParty对象自身中并不合适。更好的方法是将回复作为连接对象附加到派对对象。

首先,我们声明BirthdayPartyAttached类,它包含客人的回复。

16@QmlAnonymous
17class BirthdayPartyAttached(QObject):
18    rsvp_changed = Signal()
19
20    def __init__(self, parent=None):
21        super().__init__(parent)
22        self._rsvp = QDate()
23
24    @Property(QDate, notify=rsvp_changed, final=True)
25    def rsvp(self):
26        return self._rsvp
27
28    @rsvp.setter
29    def rsvp(self, d):
30        if self._rsvp != d:
31            self._rsvp = d
32            self.rsvp_changed.emit()

我们将它附加到BirthdayParty类,并定义qmlAttachedProperties()以返回附加的对象。

34
35@QmlElement
36@ClassInfo(DefaultProperty="guests")
37@QmlAttached(BirthdayPartyAttached)
38class BirthdayParty(QObject):
67    @staticmethod
68    def qmlAttachedProperties(self, o):
69        return BirthdayPartyAttached(o)

现在,可以在QML中使用附加对象来存储已被邀请客人的RSVP信息。

 6BirthdayParty {
 7    Boy {
 8        name: "Robert Campbell"
 9        BirthdayParty.rsvp: "2009-07-01"
10    }
11
12    Boy {
13        name: "Leo Hodges"
14        shoe_size: 10
15        BirthdayParty.rsvp: "2009-07-06"
16    }
17
18    host: Boy {
19        name: "Jack Smith"
20        shoe_size: 8
21    }
22}

最后,可以通过以下方式访问这些信息。

36    name = guest.name
37
38    rsvp_date = None
39    attached = qmlAttachedPropertiesObject(BirthdayParty, guest, False)

程序输出以下即将到来的派对的摘要

"Jack Smith" is having a birthday!
He is inviting:
    "Robert Campbell" RSVP date: "Wed Mar 1 2023"
    "Leo Hodges" RSVP date: "Mon Mar 6 2023"

下载此示例

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

"""PySide6 port of the
   qml/examples/qml/tutorials/extending-qml-advanced/advanced5-Attached-properties example
   from Qt v6.x"""

from pathlib import Path
import sys

from PySide6.QtCore import QCoreApplication
from PySide6.QtQml import QQmlComponent, QQmlEngine, qmlAttachedPropertiesObject

from person import Boy, Girl  # noqa: F401
from birthdayparty import BirthdayParty  # noqa: F401


app = QCoreApplication(sys.argv)
engine = QQmlEngine()
engine.addImportPath(Path(__file__).parent)
component = QQmlComponent(engine)
component.loadFromModule("People", "Main")
party = component.create()
if not party:
    print(component.errors())
    del engine
    sys.exit(-1)
host = party.host
print(f"{host.name} is having a birthday!")
if isinstance(host, Boy):
    print("He is inviting:")
else:
    print("She is inviting:")
for g in range(party.guestCount()):
    guest = party.guest(g)
    name = guest.name

    rsvp_date = None
    attached = qmlAttachedPropertiesObject(BirthdayParty, guest, False)
    if attached:
        rsvp_date = attached.rsvp.toString()
    if rsvp_date:
        print(f"    {name} RSVP date: {rsvp_date}")
    else:
        print(f"    {name} RSVP date: Hasn't RSVP'd")

del engine
sys.exit(0)
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

from PySide6.QtCore import QDate, QObject, ClassInfo, Property, Signal
from PySide6.QtQml import QmlAnonymous, QmlAttached, QmlElement, ListProperty

from person import Person


# To be used on the @QmlElement decorator
# (QML_IMPORT_MINOR_VERSION is optional)
QML_IMPORT_NAME = "People"
QML_IMPORT_MAJOR_VERSION = 1


@QmlAnonymous
class BirthdayPartyAttached(QObject):
    rsvp_changed = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._rsvp = QDate()

    @Property(QDate, notify=rsvp_changed, final=True)
    def rsvp(self):
        return self._rsvp

    @rsvp.setter
    def rsvp(self, d):
        if self._rsvp != d:
            self._rsvp = d
            self.rsvp_changed.emit()


@QmlElement
@ClassInfo(DefaultProperty="guests")
@QmlAttached(BirthdayPartyAttached)
class BirthdayParty(QObject):
    host_changed = Signal()
    guests_changed = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._host = None
        self._guests = []

    @Property(Person, notify=host_changed, final=True)
    def host(self):
        return self._host

    @host.setter
    def host(self, h):
        if self._host != h:
            self._host = h
            self.host_changed.emit()

    def guest(self, n):
        return self._guests[n]

    def guestCount(self):
        return len(self._guests)

    def appendGuest(self, guest):
        self._guests.append(guest)
        self.guests_changed.emit()

    @staticmethod
    def qmlAttachedProperties(self, o):
        return BirthdayPartyAttached(o)

    guests = ListProperty(Person, appendGuest, notify=guests_changed, final=True)
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

from PySide6.QtCore import QObject, Property, Signal
from PySide6.QtQml import QmlAnonymous, QmlElement

# To be used on the @QmlElement decorator
# (QML_IMPORT_MINOR_VERSION is optional)
QML_IMPORT_NAME = "People"
QML_IMPORT_MAJOR_VERSION = 1


@QmlAnonymous
class Person(QObject):
    name_changed = Signal()
    shoe_size_changed = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._name = ''
        self._shoe_size = 0

    @Property(str, notify=name_changed, final=True)
    def name(self):
        return self._name

    @name.setter
    def name(self, n):
        if self._name != n:
            self._name = n
            self.name_changed.emit()

    @Property(int, notify=shoe_size_changed, final=True)
    def shoe_size(self):
        return self._shoe_size

    @shoe_size.setter
    def shoe_size(self, s):
        self._shoe_size = s


@QmlElement
class Boy(Person):
    def __init__(self, parent=None):
        super().__init__(parent)


@QmlElement
class Girl(Person):
    def __init__(self, parent=None):
        super().__init__(parent)
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import People

BirthdayParty {
    Boy {
        name: "Robert Campbell"
        BirthdayParty.rsvp: "2009-07-01"
    }

    Boy {
        name: "Leo Hodges"
        shoe_size: 10
        BirthdayParty.rsvp: "2009-07-06"
    }

    host: Boy {
        name: "Jack Smith"
        shoe_size: 8
    }
}
module People
typeinfo coercion.qmltypes
Main 1.0 Main.qml