QMetaProperty::read:无法处理未注册的数据类型“QAbstractListModel*”

2024-10-01 09:18:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个自定义的QQuickItem,以便在我的应用程序中显示图表。我的C++版本正在工作,但是我不能让我的Python版本工作。我相信这是因为Q_DECLARE_METATYPEqRegisterMetaType没有被移植到PySide2。虽然我下面的例子没有说明这一点,但我的要求是饼图不是静态的(它可以随时更改),并且可以在运行时添加或删除任意数量的饼图。你知道吗

我的程序将运行,但它不显示任何内容,控制台上出现以下错误:

QMetaProperty::read: Unable to handle unregistered datatype 'QAbstractListModel*' for property 'CustomPieChart::model'
QMetaProperty::read: Unable to handle unregistered datatype 'QAbstractListModel*' for property 'CustomPieChart::model'
qrc:/PieChartView.qml:24:17: Unable to assign [undefined] to QAbstractItemModel*

我的代码的精简版本如下:

主.py

import sys

from PySide2.QtCore import QUrl
from PySide2.QtGui import QIcon
from PySide2.QtQml import QQmlApplicationEngine, qmlRegisterType
from PySide2.QtWidgets import QApplication

from pie_chart import CustomPieChart

import qml_rc  # noqa: F401

# Need to register PieChartModel in here somehow...

def register_quick_items() -> None:
    qmlRegisterType(CustomPieChart, "Custom.CustomPieChart", 1, 0, "CustomPieChart")


if __name__ == "__main__":
    app = QApplication(sys.argv)

    register_quick_items()

    engine = QQmlApplicationEngine()

    engine.load(QUrl("qrc:/main.qml"))

    if not engine.rootObjects():
        sys.exit(-1)

    sys.exit(app.exec_())

饼图_型号.py

from typing import Dict

from PySide2.QtCore import QAbstractListModel, QModelIndex, Qt


class PieChartModel(QAbstractListModel):
    _model_data: Dict[str, int]

    def __init__(self, parent=None):
        super().__init__(parent)
        self._model_data = []

    def rowCount(self, parent=QModelIndex()) -> int:
        return 2

    def columnCount(self, parent=QModelIndex()):
        return len(self._model_data)

    def data(self, index, role=Qt.DisplayRole):
        # Not relevant

    def headerData(self, section, orientation, role):
        # Not relevant

    def reset_with_data(self, model_data):
        self.beginResetModel()
        self._model_data = model_data
        self.endResetModel()

馅饼_图表.py

from PySide2.QtCore import Property, Signal, Slot
from PySide2.QtQuick import QQuickItem

from pie_chart_model import PieChartModel


class CustomPieChart(QQuickItem):
    model_changed = Signal(PieChartModel)
    _model: PieChartModel

    def __init__(self, parent=None):
        super().__init__(parent)
        self._model = PieChartModel(parent)

    @Property(PieChartModel, notify=model_changed)
    def model(self):
        return self._model

    @Slot(result=None)
    def reset_model(self):
        pie_slices = {
            "A": 1,
            "B": 2,
            "C": 3
        }

        self._model.reset_with_data(pie_slices)
        self.model_changed.emit(self._model)

图表视图.qml

import QtCharts 2.13
import QtQuick 2.13

import Custom.CustomPieChart 1.0

CustomPieChart {
    id: customPieChart

    Component.onCompleted: {
        customPieChart.reset_model()
    }

    ChartView {
        id: chartView
        anchors.fill: parent
        antialiasing: true
        animationOptions: ChartView.AllAnimations
        legend.visible: false

        PieSeries {
            id: pieSeries

            HPieModelMapper {
                model: customPieChart.model
                labelsRow: 0
                valuesRow: 1
            }
        }
    }
}

主.qml

import QtQuick 2.13
import QtQuick.Controls 2.13

ApplicationWindow {
    visible: true
    width: 500
    height: 500

    PieChartView {
        anchors.fill: parent
    }
}

质量保证书

<RCC>
    <qresource prefix="/">
        <file>main.qml</file>
        <file>PieChartView.qml</file>
    </qresource>
</RCC>

Tags: tofromimportselfdatamodeldefsys
1条回答
网友
1楼 · 发布于 2024-10-01 09:18:42

您有以下错误:

您有以下错误:

    在C++中,不需要使用QyDeCurrayMeta或QRealStEyType,以便可以从QML访问模型,只需将其登记为QObjQuy属性,同样在PySID2中也会发生。

  • 在具有2列和n行的模型中,它不能是QAbstractListModel,因此必须将其更改为QAbstractTableModel。

  • 模型必须是一个常量属性,因为在您的逻辑中您不更改它,而只重置它的信息。

  • 虽然我不知道这是否是一个错误,但如果你想在图表中看到模型的数据,你必须把它与一个系列相关联。

综上所述,解决方案是:

饼图_型号.py

from typing import Dict

from PySide2.QtCore import QAbstractTableModel, QModelIndex, Qt


class PieChartModel(QAbstractTableModel):
    _model_data: Dict[str, int]
    def __init__(self, parent=None):
        super().__init__(parent)
        self._model_data = []

    def rowCount(self, parent=QModelIndex()) -> int:
        return 2

    def columnCount(self, parent=QModelIndex()) -> int:
        return len(self._model_data)

    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid():
            return
        r = index.row()
        c = index.column()
        if 0 <= r < self.rowCount() and 0 <= c < self.columnCount():
            if role == Qt.DisplayRole:
                if r == 0:
                    return list(self._model_data.keys())[c]
                elif r == 1:
                    return list(self._model_data.values())[c]

    def reset_with_data(self, model_data):
        self.beginResetModel()
        self._model_data = model_data
        self.endResetModel()

馅饼_图表.py

from PySide2.QtCore import Property, Slot, QObject
from PySide2.QtQuick import QQuickItem

from pie_chart_model import PieChartModel


class CustomPieChart(QQuickItem):
    _model: PieChartModel

    def __init__(self, parent=None):
        super().__init__(parent)
        self._model = PieChartModel(self)

    @Property(QObject, constant=True)
    def model(self):
        return self._model

    @Slot(result=None)
    def reset_model(self):
        pie_slices = {
            "A": 1,
            "B": 2,
            "C": 3
        }

        self._model.reset_with_data(pie_slices)

图表视图.qml

import QtCharts 2.13
import QtQuick 2.13

import Custom.CustomPieChart 1.0

CustomPieChart {
    id: customPieChart

    Component.onCompleted: {
        customPieChart.reset_model()
    }

    ChartView {
        id: chartView
        anchors.fill: parent
        antialiasing: true
        animationOptions: ChartView.AllAnimations
        legend.visible: false

        PieSeries{
            id: pie_series
        }

        HPieModelMapper {
            series: pie_series
            model: customPieChart.model
            labelsRow: 0
            valuesRow: 1
        }
    }
}

相关问题 更多 >