为QML的ListView公开QObject的QAbstractListModel。良好的做法?

为QML的ListView公开QObject的QAbstractListModel。良好的做法?

问题描述:

因此,我有这样的想法,即使用QObject的Q_PROPERTY而不是角色名称QAbstractListModel将通知属性暴露给QML。为QML的ListView公开QObject的QAbstractListModel。良好的做法?

我的问题是,如果这是一个很好的做法,因为使用继承自QAbstractItemModel的类有点不自然。

让我更详细地解释一下。
因此,对于QML创建C++模型的推荐方法是:

  1. 继承QAbstractListModel(或其他)创建自定义模式。
  2. 过载rowCount()
  3. 定义您自己的数据角色。

e.g:

enum DataRoles { 
    Name = Qt::UserRole + 1, 
    Description, 
    CustomData 
}; 

... 


QHash<int, QByteArray> TestList::roleNames() const 
{ 
    QHash<int, QByteArray> res; 
    res[static_cast<int>(DataRoles::Name)] = "name"; 
    res[static_cast<int>(DataRoles::Description)] = "description"; 
    res[static_cast<int>(DataRoles::CustomData)] = "customData"; 

    return res; 
} 
  1. 返回对应于重载data()成员函数的数据。
  2. 如:

    QVariant TestList::data(const QModelIndex & index, int role) const 
    { 
        QVariant result = QVariant(); 
    
        if (index.isValid() == true) { 
         EntityPtr entityPtr = entities_.at(index.row()); 
    
         switch (role) { 
         case DataRoles::Name: 
          result = entityPtr->name(); 
          break; 
         case DataRoles::Description: 
          result = entityPtr->description(); 
          break; 
         case DataRoles::CustomData: 
          result = entityPtr->customData(); 
          break; 
         } 
        } 
    
        return result; 
    } 
    

    比,在QML的情况下注册您的模型实例后,您可以访问实体字段的名字)ListView的委托,在rolesNames定义(如:

    ListView { 
        model: yourModelInstance 
        ... 
        delegate: Item { 
         ... 
         Text { 
          text: name // access DataRoles::Name 
         } 
         ... 
        } 
    } 
    

    国际海事组织,这种实现是好的,但是当涉及到从C++端改变属性,你应该调用dataChaged()信号QAbstractListView对实体的属性

    而且我希望能够自动通知有关更改的视图,例如,当我打电话给entity->setName()

    我的想法是只注册一个数据角色,例如“对象”,将返回整个QObject的,这将有Q_PROPERTY秒,然后从QML喜欢访问:

    Text { 
        text: object.name //access `name` Q_PROPERTY of the object 
    } 
    

    这样,如果制定者会发出正确的信号,在Q_PROPERTY申报登记,QML侧会自动通知关于设置新值的更改。所以问题是,如果这是实现我的目标的好方法,因为正如我上面所说的那样,这感觉有点不自然,而Qt库很好地表明你正在做错某事使错误的事情变得很难(不自然)。

    编辑

    由于被要求在评论中,我做了我展示要达到什么样的一个小的Qt的示例应用程序。

    混帐回购协议 - https://github.com/shtemberko/SO_question_temp

开始=>
+1

您可以轻松创建一个包装'QObjectList'的模型,并将对象的某个或某些属性作为单独的单元格公开。你不会传递任何'QObject's - 'QVariant'永远不会与他们合作。它是一个值类,'QObject'不是一个值类。 –

+0

'QObjectList'只是'QList '的typedef,不是吗?我会面临同样的问题,以通知有关道具被改变。整个目标是在每次他想要改变一些属性或者以某种方式从对象设置器函数中通知模型时,开发者有义务调用dataChanged信号。 – rsht

+0

我同意你的意见。不过,如果不直接使用QObject的属性,我只会看到一个可能的实现 - 将每个实体的每个“xxxChanged()”信号连接到该模型的dataChaged()信号上。这听起来不像是一件有趣的事情来维持+ imo,会导致更强的耦合,这很少有好处。另一个选择是每次用户想要更改数据时使用QAbstractListView的setData()。这将导致从QML改变数据的可能性+其他封装问题。 – rsht

我认为你需要为每个属性在实体的PropertyChanged信号。然后将propertyChanged链接到dataChanged信号。当你setName或setPosition时,发出propertyChanged信号。