扩展QML - 使用列表属性类型¶
这是关于使用Python扩展QML的教程系列中的第五个示例,该系列共有6个示例。
目前,一个PieChart
只能有一个PieSlice。
理想情况下,图表应该
有多个切片,具有不同的颜色和大小。为了实现这一点,我们可以
有一个slices
属性,该属性接受一个PieSlice
项目的列表:
4import Charts
5import QtQuick
6
7Item {
8 width: 300; height: 200
9
10 PieChart {
11 anchors.centerIn: parent
12 width: 100; height: 100
13
14 slices: [
15 PieSlice {
16 anchors.fill: parent
17 color: "red"
18 fromAngle: 0; angleSpan: 110
19 },
20 PieSlice {
21 anchors.fill: parent
22 color: "black"
23 fromAngle: 110; angleSpan: 50
24 },
25 PieSlice {
26 anchors.fill: parent
27 color: "blue"
28 fromAngle: 160; angleSpan: 100
29 }
30 ]
31 }
32}
为此,我们将PieChart
中的pieSlice
属性替换为
slices
属性,声明为
ListProperty
类型的类变量。
ListProperty
类允许在
QML扩展中创建列表属性。我们将pieSlice()
函数替换为返回切片列表的slices()
函数,并添加一个内部的appendSlice()
函数(如下所述)。我们还使用一个列表来存储内部的切片列表,如_slices
所示:
62@QmlElement
63class PieChart (QQuickItem):
64 def __init__(self, parent=None):
65 QQuickItem.__init__(self, parent)
75 self._name = value
76
77 def appendSlice(self, _slice):
78 _slice.setParentItem(self)
79 self._slices.append(_slice)
尽管slices
属性没有关联的设置器,但由于ListProperty
的工作方式,它仍然可以修改。我们指示每当从QML发出请求向列表中添加项目时,应调用内部的PieChart.appendSlice()
函数。
appendSlice()
函数简单地像之前一样设置父项,并将新项添加到 _slices
列表中。如你所见,ListProperty
的 append 函数被调用时带有两个参数:列表属性和要追加的项。
PieSlice
类也被修改为包含 fromAngle
和 angleSpan
属性,并根据这些值绘制切片。如果您已经阅读了本教程的前几页,这是一个简单的修改,因此这里不显示代码。
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import Charts
import QtQuick
Item {
width: 300; height: 200
PieChart {
anchors.centerIn: parent
width: 100; height: 100
slices: [
PieSlice {
anchors.fill: parent
color: "red"
fromAngle: 0; angleSpan: 110
},
PieSlice {
anchors.fill: parent
color: "black"
fromAngle: 110; angleSpan: 50
},
PieSlice {
anchors.fill: parent
color: "blue"
fromAngle: 160; angleSpan: 100
}
]
}
}
# 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/tutorials/extending-qml/chapter5-listproperties example from Qt v5.x"""
import os
from pathlib import Path
import sys
from PySide6.QtCore import Property, QUrl
from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide6.QtQml import QmlElement, ListProperty
from PySide6.QtQuick import QQuickPaintedItem, QQuickView, QQuickItem
# To be used on the @QmlElement decorator
# (QML_IMPORT_MINOR_VERSION is optional)
QML_IMPORT_NAME = "Charts"
QML_IMPORT_MAJOR_VERSION = 1
@QmlElement
class PieSlice (QQuickPaintedItem):
def __init__(self, parent=None):
QQuickPaintedItem.__init__(self, parent)
self._color = QColor()
self._fromAngle = 0
self._angleSpan = 0
@Property(QColor, final=True)
def color(self):
return self._color
@color.setter
def color(self, value):
self._color = value
@Property(int, final=True)
def fromAngle(self):
return self._angle
@fromAngle.setter
def fromAngle(self, value):
self._fromAngle = value
@Property(int, final=True)
def angleSpan(self):
return self._angleSpan
@angleSpan.setter
def angleSpan(self, value):
self._angleSpan = value
def paint(self, painter):
pen = QPen(self._color, 2)
painter.setPen(pen)
painter.setRenderHints(QPainter.RenderHint.Antialiasing, True)
painter.drawPie(
self.boundingRect().adjusted(1, 1, -1, -1), self._fromAngle * 16, self._angleSpan * 16)
@QmlElement
class PieChart (QQuickItem):
def __init__(self, parent=None):
QQuickItem.__init__(self, parent)
self._name = u''
self._slices = []
@Property(str, final=True)
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
def appendSlice(self, _slice):
_slice.setParentItem(self)
self._slices.append(_slice)
slices = ListProperty(PieSlice, appendSlice, final=True)
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
view.setSource(QUrl.fromLocalFile(qml_file))
if view.status() == QQuickView.Status.Error:
sys.exit(-1)
view.show()
res = app.exec()
# Deleting the view before it goes out of scope is required to make sure all child QML instances
# are destroyed in the correct order.
del view
sys.exit(res)