2016-09-27 74 views
1

我从自定义子类(实现here)中显示GridView中的数据。添加和删​​除项目工作正常,QML被通知更改和转换工作正常。
现在我试图在模型中设置一个Item的属性,并让QML对它做出反应。问题是,QML中的onPropertyChanged未被调用。QML从C++属性中未注册属性更改

这里是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 

回答

0

两个有些靠不住的行为这里出了问题。首先,因为在

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

dataChanged的++的发射在导致更新错误项目错误的索引。所有的二,

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

失踪的第三个参数,因为在另一次尝试我试过内联定义向量的方法不对,我没觉得这是问题的时候了。正确的电话会在这里

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); 

我的错误。

但是在另一个说明中,由于角色名称索引似乎是平台相关的,并且表明从模型的变化有点肮脏,所以更好的解决方案(如Kevin Krammer所建议的)将重写itemmodel为仅包含一个物业,这是QObject项目。这样QML 被通知的变更项目的属性。

+1

由于您的模型具有基于QObject的项目,因此您也可以只有一个角色返回相应的对象并直接绑定到该对象的属性。 然后,您不需要发出dataChanged(),除非特定索引处的对象发生更改。 也意味着你不需要像“与角色名称检查”这样的评论,因为你只有一个,固定的角色 –

+0

这听起来比我所做的更好。你有关于我的模型变化如何的来源? –

+0

基本上你有一个角色,当你在'data()'中要求这个角色时,你只需返回该索引的QObject指针。 假设你的'roleNames()'将其映射到属性名'object',那么你的QML可以执行'someDelegateProperty:model.object.propertyOfTheObject'(或者如果你更喜欢不太特定的语法,不需要'model.') –