扩展QML - 连接到C++方法和信号¶
这是关于使用Python扩展QML的教程系列中的第二个示例,该系列共有6个示例。
假设我们希望PieChart
有一个clearChart()
方法,该方法可以清除图表并发出chartCleared
信号。我们的app.qml
将能够调用clearChart()
并接收chartCleared()
信号,如下所示:
4import Charts
5import QtQuick
6
7Item {
8 width: 300; height: 200
9
10 PieChart {
11 id: aPieChart
12 anchors.centerIn: parent
13 width: 100; height: 100
14 color: "red"
15
16 onChartCleared: console.log("The chart has been cleared")
17 }
18
19 MouseArea {
20 anchors.fill: parent
21 onClicked: aPieChart.clearChart()
22 }
23
24 Text {
25 anchors {
26 bottom: parent.bottom;
27 horizontalCenter: parent.horizontalCenter;
28 bottomMargin: 20
29 }
30 text: "Click anywhere to clear the chart"
31 }
32}
为此,我们在C++类中添加了一个clearChart()
方法和一个chartCleared()
信号:
54
55 @Slot() # This should be something like @Invokable
56 def clearChart(self):
57 self.color = Qt.transparent
58 self.update()
使用@Slot
使得clearChart()
方法对Qt元对象系统可用,进而对QML可用。该方法简单地将颜色更改为Qt::transparent
,重新绘制图表,然后发出chartCleared()
信号:
21
22@QmlElement
23class PieChart(QQuickPaintedItem):
24
现在当我们运行应用程序并点击窗口时,饼图消失, 应用程序输出:
qml: The chart has been cleared
# 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/chapter2-methods example from Qt v5.x"""
import os
from pathlib import Path
import sys
from PySide6.QtCore import Property, Signal, Slot, Qt, QUrl
from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide6.QtQml import QmlElement
from PySide6.QtQuick import QQuickPaintedItem, QQuickView
# To be used on the @QmlElement decorator
# (QML_IMPORT_MINOR_VERSION is optional)
QML_IMPORT_NAME = "Charts"
QML_IMPORT_MAJOR_VERSION = 1
@QmlElement
class PieChart(QQuickPaintedItem):
chartCleared = Signal()
nameChanged = Signal()
def __init__(self, parent=None):
QQuickPaintedItem.__init__(self, parent)
self._name = u''
self._color = QColor()
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), 90 * 16, 290 * 16)
@Property(QColor, final=True)
def color(self):
return self._color
@color.setter
def color(self, value):
self._color = value
@Property(str, notify=nameChanged, final=True)
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
@Slot() # This should be something like @Invokable
def clearChart(self):
self.color = Qt.transparent
self.update()
self.chartCleared.emit()
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)
// 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 {
id: aPieChart
anchors.centerIn: parent
width: 100; height: 100
color: "red"
onChartCleared: console.log("The chart has been cleared")
}
MouseArea {
anchors.fill: parent
onClicked: aPieChart.clearChart()
}
Text {
anchors {
bottom: parent.bottom;
horizontalCenter: parent.horizontalCenter;
bottomMargin: 20
}
text: "Click anywhere to clear the chart"
}
}