扩展QML(高级) - 分组属性¶
这是使用生日派对示例来展示QML一些高级功能的6个示例系列中的第四个。
需要更多关于客人鞋子的信息。除了他们的尺寸,我们还想存储鞋子的颜色、品牌和价格。这些信息存储在ShoeDescription
类中。
14
15@QmlAnonymous
16class ShoeDescription(QObject):
17 brand_changed = Signal()
18 size_changed = Signal()
19 price_changed = Signal()
20 color_changed = Signal()
21
22 def __init__(self, parent=None):
23 super().__init__(parent)
24 self._brand = ''
25 self._size = 0
26 self._price = 0
27 self._color = QColor()
28
29 @Property(str, notify=brand_changed, final=True)
30 def brand(self):
31 return self._brand
32
33 @brand.setter
34 def brand(self, b):
35 if self._brand != b:
36 self._brand = b
37 self.brand_changed.emit()
38
39 @Property(int, notify=size_changed, final=True)
40 def size(self):
41 return self._size
42
43 @size.setter
44 def size(self, s):
45 if self._size != s:
46 self._size = s
47 self.size_changed.emit()
48
49 @Property(float, notify=price_changed, final=True)
50 def price(self):
51 return self._price
52
53 @price.setter
54 def price(self, p):
55 if self._price != p:
56 self._price = p
57 self.price_changed.emit()
58
59 @Property(QColor, notify=color_changed, final=True)
60 def color(self):
61 return self._color
62
63 @color.setter
64 def color(self, c):
65 if self._color != c:
66 self._color = c
每个人现在有两个属性,一个name
和一个鞋子描述shoe
。
69
70@QmlAnonymous
71class Person(QObject):
72 name_changed = Signal()
73
74 def __init__(self, parent=None):
75 super().__init__(parent)
76 self._name = ''
77 self._shoe = ShoeDescription()
78
79 @Property(str, notify=name_changed, final=True)
80 def name(self):
81 return self._name
82
83 @name.setter
84 def name(self, n):
85 if self._name != n:
86 self._name = n
87 self.name_changed.emit()
88
89 @Property(ShoeDescription, final=True)
90 def shoe(self):
为鞋子描述的每个元素指定值是可行的,但有点重复。
26 Girl {
27 name: "Anne Brown"
28 shoe.size: 7
29 shoe.color: "red"
30 shoe.brand: "Job Macobs"
31 shoe.price: 699.99
32 }
分组属性提供了一种更优雅的方式来分配这些属性。
与逐个为每个属性赋值不同,可以将各个值作为一组传递给shoe
属性,使代码更具可读性。无需进行任何更改即可启用此功能,因为它默认适用于所有QML。
9 host: Boy {
10 name: "Bob Jones"
11 shoe { size: 12; color: "white"; brand: "Bikey"; price: 90.0 }
12 }
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from __future__ import annotations
"""PySide6 port of the
qml/examples/qml/tutorials/extending-qml-advanced/advanced4-Grouped-properties example
from Qt v6.x"""
from pathlib import Path
import sys
from PySide6.QtCore import QCoreApplication
from PySide6.QtQml import QQmlComponent, QQmlEngine
from person import Boy, Girl # noqa: F401
from birthdayparty import BirthdayParty # noqa: F401
if __name__ == '__main__':
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:")
best_shoe = None
for g in range(party.guestCount()):
guest = party.guest(g)
name = guest.name
print(f" {name}")
if not best_shoe or best_shoe.shoe.price < guest.shoe.price:
best_shoe = guest
if best_shoe:
print(f"{best_shoe.name} is wearing the best shoes!")
del engine
sys.exit(0)
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from __future__ import annotations
from PySide6.QtCore import QObject, ClassInfo, Property, Signal
from PySide6.QtQml import 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
@QmlElement
@ClassInfo(DefaultProperty="guests")
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()
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 __future__ import annotations
from PySide6.QtCore import QObject, Property, Signal
from PySide6.QtGui import QColor
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 ShoeDescription(QObject):
brand_changed = Signal()
size_changed = Signal()
price_changed = Signal()
color_changed = Signal()
def __init__(self, parent=None):
super().__init__(parent)
self._brand = ''
self._size = 0
self._price = 0
self._color = QColor()
@Property(str, notify=brand_changed, final=True)
def brand(self):
return self._brand
@brand.setter
def brand(self, b):
if self._brand != b:
self._brand = b
self.brand_changed.emit()
@Property(int, notify=size_changed, final=True)
def size(self):
return self._size
@size.setter
def size(self, s):
if self._size != s:
self._size = s
self.size_changed.emit()
@Property(float, notify=price_changed, final=True)
def price(self):
return self._price
@price.setter
def price(self, p):
if self._price != p:
self._price = p
self.price_changed.emit()
@Property(QColor, notify=color_changed, final=True)
def color(self):
return self._color
@color.setter
def color(self, c):
if self._color != c:
self._color = c
self.color_changed.emit()
@QmlAnonymous
class Person(QObject):
name_changed = Signal()
def __init__(self, parent=None):
super().__init__(parent)
self._name = ''
self._shoe = ShoeDescription()
@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(ShoeDescription, final=True)
def shoe(self):
return self._shoe
@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 QtQuick
import People
BirthdayParty {
host: Boy {
name: "Bob Jones"
shoe { size: 12; color: "white"; brand: "Bikey"; price: 90.0 }
}
Boy {
name: "Leo Hodges"
shoe { size: 10; color: "black"; brand: "Thebok"; price: 59.95 }
}
Boy { name: "Jack Smith"
shoe {
size: 8
color: "blue"
brand: "Luma"
price: 19.95
}
}
Girl {
name: "Anne Brown"
shoe.size: 7
shoe.color: "red"
shoe.brand: "Job Macobs"
shoe.price: 699.99
}
}
module People
typeinfo coercion.qmltypes
Main 1.0 Main.qml