PySide Qt dataChanged.emit() 不工作但 LayoutChanged.emit 工作

PySide Qt dataChanged.emit() not working but LayoutChanged.emit works

from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine, qmlRegisterType
from PySide6.QtCore import QObject, Signal, Slot, Property, Qt,QUrl, QTimer, QAbstractListModel


class CpuLoadModel(QAbstractListModel):
    def __init__(self):
        QAbstractListModel.__init__(self)

        self.__update_timer = QTimer(self)
        self.__update_timer.setInterval(1000)
        self.__update_timer.timeout.connect(self.__update)
        self.__update_timer.start()

        self.todos = []

    def __update(self):
        self.todos.append(random.randint(0, 99))
        self.layoutChanged.emit()
        print(self.todos)
        self.dataChanged.emit(self.index,self.index,[])

    def data(self, index, role):
        if role == Qt.DisplayRole:
            text = self.todos[index.row()]
            print(f"Text: {index.row()} role : {role}")
            print("--------")
            return text

    def rowCount(self, index):
        return len(self.todos)


if __name__ == '__main__':
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    qmlRegisterType(CpuLoadModel, 'PsUtils', 1, 0, 'CpuLoadModel')
    engine.load(QUrl("main.qml"))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec())

self.dataChange.emit 方法根本不起作用,但是 self.LayoutChange.emit 有效,但存在 qml

中的错误
TypeError: Cannot read property 'width' of null

layoutChanged 信号必须在模型中的某些东西发生变化时发出(例如它已被重新排序),并且 dataChanged 当任何项目更改数据但其中 none 用于指示添加了行,在这种情况下,它必须使用 beginInsertRows 和 endInsertRows 方法。

def __update(self):
    self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
    self.todos.append(random.randint(0, 99))
    self.endInsertRows()

也改为:

def rowCount(self, index=QModelIndex()):
    if index.isValid():
        return 0
    return len(self.todos)
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.0

import PsUtils 1.0

Window {
    id: root
    width: 640
    height: 480
    visible: true
    title: "CPU Load"

    ListView {
        id:listviewId
        anchors.fill: parent
        model: CpuLoadModel { }
        delegate: Rectangle {
            width: listviewId.width
            height: 30;
            color: "white"

            Rectangle {
                id: bar
                width: listviewId.width * display / 100.0
                height: 30
                color: "green"
            }

            Text {
                anchors.verticalCenter: parent.verticalCenter
                x: Math.min(bar.x + bar.width + 5, parent.width-width)
                text: display + "%"
            }
        }
    }
}

基本上错误是 QML 中的 parent.width 我们最好使用 id 来引用元素而不是使用 parent.width(使用 elementId.width)