扩展QML(高级)- 分组属性#

这是关于生日派对的一系列6个示例的第4个,用于使用生日派对的示例来演示的一些QML的高级功能。

需要更多关于客人鞋子的信息。除了尺寸外,我们还想存储鞋子的颜色、品牌和价格。此类信息存储在ShoeDescription类中。

14@QmlAnonymous
15class ShoeDescription(QObject):
16    brand_changed = Signal()
17    size_changed = Signal()
18    price_changed = Signal()
19    color_changed = Signal()
20
21    def __init__(self, parent=None):
22        super().__init__(parent)
23        self._brand = ''
24        self._size = 0
25        self._price = 0
26        self._color = QColor()
27
28    @Property(str, notify=brand_changed, final=True)
29    def brand(self):
30        return self._brand
31
32    @brand.setter
33    def brand(self, b):
34        if self._brand != b:
35            self._brand = b
36            self.brand_changed.emit()
37
38    @Property(int, notify=size_changed, final=True)
39    def size(self):
40        return self._size
41
42    @size.setter
43    def size(self, s):
44        if self._size != s:
45            self._size = s
46            self.size_changed.emit()
47
48    @Property(float, notify=price_changed, final=True)
49    def price(self):
50        return self._price
51
52    @price.setter
53    def price(self, p):
54        if self._price != p:
55            self._price = p
56            self.price_changed.emit()
57
58    @Property(QColor, notify=color_changed, final=True)
59    def color(self):
60        return self._color
61
62    @color.setter
63    def color(self, c):
64        if self._color != c:
65            self._color = c
66            self.color_changed.emit()

现在每个人有两个属性,一个是name,另一个是鞋描述shoe

69@QmlAnonymous
70class Person(QObject):
71    name_changed = Signal()
72
73    def __init__(self, parent=None):
74        super().__init__(parent)
75        self._name = ''
76        self._shoe = ShoeDescription()
77
78    @Property(str, notify=name_changed, final=True)
79    def name(self):
80        return self._name
81
82    @name.setter
83    def name(self, n):
84        if self._name != n:
85            self._name = n
86            self.name_changed.emit()
87
88    @Property(ShoeDescription, final=True)
89    def shoe(self):
90        return self._shoe

指定鞋描述的每个元素的值是可行的,但有点冗余。

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

"""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 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 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