扩展 QML - 连接到 C++ 方法与信号#

这是关于使用 Python 扩展 QML 的 6 个示例系列中的第二个示例。

假设我们想让 PieChart 具有可以在清除图表后发出 chartCleared 信号的 clearChart() 方法。

 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    @Slot()  # This should be something like @Invokable
55    def clearChart(self):
56        self.color = Qt.transparent
57        self.update()
58        self.chartCleared.emit()

使用 Slot 装饰器使 clearChart() 方法可用于 Qt 元对象系统,进而可用于 QML。该方法只是将颜色更改为 Qt::transparent,重新绘制图表,然后发出 chartCleared() 信号。

21@QmlElement
22class PieChart(QQuickPaintedItem):
23
24    chartCleared = Signal()

现在当运行应用程序并点击窗口时,饼图消失,应用程序输出

qml: The chart has been cleared

下载 示例

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

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