扩展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