扩展QML(高级)- 生日派对基础项目#

这是由6个示例组成的一系列教程的第一个示例,用生日派对的例子来展示QML的一些高级特性。下面解释的各种功能的代码基于这个生日派对项目,并依赖于基本教程中的某些材料。然后,这个简单的例子被扩展以展示下面的各种QML扩展。每个新扩展的完整代码可以在相应页面的结尾找到。

基础项目定义了Person类和BirthdayParty类,分别模型化参会者和派对本身。

13@QmlElement
14class Person(QObject):
15    name_changed = Signal()
16    shoe_size_changed = Signal()
17
18    def __init__(self, parent=None):
19        super().__init__(parent)
20        self._name = ''
21        self._shoe_size = 0
22
23    @Property(str, notify=name_changed, final=True)
24    def name(self):
25        return self._name
26
27    @name.setter
28    def name(self, n):
29        if self._name != n:
30            self._name = n
31            self.name_changed.emit()
32
33    @Property(int, notify=shoe_size_changed, final=True)
34    def shoe_size(self):
35        return self._shoe_size
36
37    @shoe_size.setter
38    def shoe_size(self, s):
39        if self._shoe_size != s:
40            self._shoe_size = s
41            self.shoe_size_changed.emit()
16@QmlElement
17class BirthdayParty(QObject):
18    host_changed = Signal()
19    guests_changed = Signal()
20
21    def __init__(self, parent=None):
22        super().__init__(parent)
23        self._host = None
24        self._guests = []
25
26    @Property(Person, notify=host_changed, final=True)
27    def host(self):
28        return self._host
29
30    @host.setter
31    def host(self, h):
32        if self._host != h:
33            self._host = h
34            self.host_changed.emit()
35
36    def guest(self, n):
37        return self._guests[n]
38
39    def guestCount(self):
40        return len(self._guests)
41
42    def appendGuest(self, guest):
43        self._guests.append(guest)
44        self.guests_changed.emit()
45
46    guests = ListProperty(Person, appendGuest, notify=guests_changed, final=True)

然后所有关于派对的信息都可以存储在相应的QML文件中。

 4import People
 5
 6BirthdayParty {
 7    host: Person {
 8        name: "Bob Jones"
 9        shoe_size: 12
10    }
11    guests: [
12        Person { name: "Leo Hodges" },
13        Person { name: "Jack Smith" },
14        Person { name: "Anne Brown" }
15    ]
16}

main.py文件创建了一个简单的壳式应用程序,显示今天是哪位朋友的生日以及邀请了谁参加派对。

17app = QCoreApplication(sys.argv)
18engine = QQmlEngine()
19engine.addImportPath(Path(__file__).parent)
20component = QQmlComponent(engine)
21component.loadFromModule("People", "Main")

该应用程序输出了以下派对总结

"Bob Jones" is having a birthday!
They are inviting:
    "Leo Hodges"
    "Jack Smith"
    "Anne Brown"

Outlook#

以下章节介绍了如何通过继承和强制转换来支持添加对BoyGirl参会者的支持,而不是仅仅支持Person;如何使用默认属性来隐式地将宴会的参会者指定为客人;如何将属性作为一组而不是单个属性进行分配;如何使用附加对象来跟踪被邀请客人的回复;如何使用属性值源在一段时间内显示生日快乐歌的歌词;以及如何将第三方对象暴露给QML。

下载此示例

# Copyright (C) 2023 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/advanced1-Base-project 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 Person  # 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!\nThey are inviting:")
for g in range(party.guestCount()):
    name = party.guest(g).name
    print(f"    {name}")
del engine
sys.exit(0)
# Copyright (C) 2023 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 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
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) 2023 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 QmlElement

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


@QmlElement
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):
        if self._shoe_size != s:
            self._shoe_size = s
            self.shoe_size_changed.emit()
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import People

BirthdayParty {
    host: Person {
        name: "Bob Jones"
        shoe_size: 12
    }
    guests: [
        Person { name: "Leo Hodges" },
        Person { name: "Jack Smith" },
        Person { name: "Anne Brown" }
    ]
}
module People
typeinfo coercion.qmltypes
Main 1.0 Main.qml