QML没有从c++属性中注册属性更改

QML not registering property change from C++ property

本文关键字:属性 注册 c++ QML      更新时间:2023-10-16

我正在显示来自自定义QAbstractListItem子类(在这里实现)的GridView中的数据。添加和删除项目工作正常,QML通知更改和转换工作正常。
现在我试图在模型中设置一个Item的属性,并让QML对其进行反应。问题是,QML内部的onPropertyChanged没有被调用。

下面是c++中的属性:
// item.h
Q_PROPERTY(bool pToBeDeleted READ toBeDeleted NOTIFY toBeDeletedChanged)
// item.cpp
void Item::requestDelete()
{
    toBeDeleted_m = true;
    qDebug() << "emitting";
    emit toBeDeletedChanged();
}

这是GridView的样子:

// main.qml
GridView {
    id: grid
    // ...
    model: empty
    delegate: customComponent {
        toBeDeleted: pToBeDeleted
    }
    ListModel {
        id: empty
    }
}

程序启动时,gridmodel设置为我的itemmodel。
这是看不到更改的QML类型:

// customComponentForm.ui.qml
Item {
    property bool toBeDeleted: false
}
// customComponent.qml
CustomComponentForm {
    onToBeDeletedChanged: {
        console.debug("change")
    }
}

现在当我从模型内部像这样调用这个方法时:

this->items.at(i++)->requestDelete();

输出显示emitting,不显示change


我试图包含

emit dataChanged(createIndex(i, 0), createIndex(i, 0));

有时会导致onToBeDeletedChanged被称为,但这也会导致错误

的一些不稳定行为。
DelegateModel::item: index out range 3 3

这里出了两个问题。首先,因为

上的++
this->items.at(i++)->requestDelete();

dataChanged emit有错误的索引,导致错误的项被更新。其次,

emit dataChanged(createIndex(i, 0), createIndex(i, 0));

缺少第三个参数,并且由于在另一次尝试中,我以错误的方式尝试内联定义Vector,因此我没有立即发现这是问题所在。这里的正确调用应该是

QVector<int> v;
v.append(Qt::UserRole + 7 + 1);
// pToBeDeleted being the 7th property, always check this with
// roleNames()[Qt::UserRole + i + 1]. It should say your property.
emit dataChanged(createIndex(i, 0), createIndex(i, 0), v);

我的错误。

但另一方面,由于rolename索引似乎是平台相关的,并且从模型发出更改信号是一种不太好的方法,因此更好的解决方案(如Kevin Krammer所建议的)是重写itemmodel,使其只包含单个属性,即QObject项。这样QML 就会被通知条目属性所发生的更改。