2017-06-27 62 views
2

我有一个QML ListView,它使用QAbstractListModel子类作为模型。从QML ListView操纵QAbstractListModel中的数据

ListView { 
    id: myListView 
    x: 208 
    y: 19 
    width: 110 
    height: 160 
    delegate: myListDelegate {} 
    model: MyListModel 
    opacity: 0 
} 

该模型是一个列表MyListItem s。

class MyListModel : public QAbstractListModel 
{ 
    Q_OBJECT 
public: 
    enum MyRoles { 
     HeadingRole = Qt::UserRole + 1, 
     DescriptionRole, 
     QuantityRole 
    }; 

    explicit MyListModel(QObject *parent = 0); 

    void addMyListItem(const MyListItem &item); 
    int rowCount(const QModelIndex & parent = QModelIndex()) const; 
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; 
    void dropList(); 

private: 
    QList<MyListItem> m_list; 

}; 

在代表我有一个鼠标区域。

我如何可以拦截在鼠标区域点击,并挑选,从我的QList模式MyListItem和地方发送它的应用程序的C++部分里面?

+0

你尝试创建MyListItem中的鼠标区域或重写onClick方法? –

+0

@GabrieldeGrimouard我打算'QList '元素,而不是'myListItem'作为ListView委托 – Zhigalin

+0

您可以定义一个新角色('QAbstractItemModel :: roleNames'),它返回'MyListItem'并在'onClick'事件中使用它描述[here](http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel-subclass) – m7913d

回答

1

评论提及将返回指向MyListItem的指针从data()改为QML并以QML格式访问和修改它。这要求您的MyListItem继承自QObject并为您希望在QML中访问的每个成员添加一个Q_PROPERTY。它还需要密切关注对象所有权(QQmlEngine::ObjectOwnership)。

还有另一种方法:执行QAbstractListModel::setData()QAbstractListModel::roleNames(),模型内容可以从QML改变,如model.roleName = foo

低于最小工作示例,其中每个被点击的委托时间加倍量:

C++:

struct MyListItem 
{ 
    QString heading; 
    QString description; 
    int quantity; 
}; 

class MyListModel : public QAbstractListModel 
{ 
    Q_OBJECT 
    Q_ENUMS(MyRoles) 
public: 
    enum MyRoles { 
     HeadingRole = Qt::UserRole + 1, 
     DescriptionRole, 
     QuantityRole 
    }; 

    using QAbstractListModel::QAbstractListModel; 

    QHash<int,QByteArray> roleNames() const override { 
     return { { HeadingRole, "heading" }, 
      { DescriptionRole, "description" }, 
      { QuantityRole, "quantity" }, 
     }; 
    } 
    int rowCount(const QModelIndex & parent = QModelIndex()) const override { 
     if (parent.isValid()) 
      return 0; 
     return m_list.size(); 
    } 

    bool setData(const QModelIndex &index, const QVariant &value, int role) override 
    { 
     if (!hasIndex(index.row(), index.column(), index.parent()) || !value.isValid()) 
      return false; 

     MyListItem &item = m_list[index.row()]; 
     if (role == DescriptionRole) item.description = value.toString(); 
     else if (role == HeadingRole) item.heading = value.toString(); 
     else if (role == QuantityRole) item.quantity = value.toInt(); 
     else return false; 

     emit dataChanged(index, index, { role }); 

     return true ; 

    } 

    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override { 
     if (!hasIndex(index.row(), index.column(), index.parent())) 
      return {}; 

     const MyListItem &item = m_list.at(index.row()); 
     if (role == DescriptionRole) return item.description; 
     if (role == HeadingRole) return item.heading; 
     if (role == QuantityRole) return item.quantity; 

     return {}; 
    } 

private: 
    QVector<MyListItem> m_list = { 
     { "heading 1", "description 1", 1 }, 
     { "heading 2", "description 2", 42 }, 
     { "heading 3", "description 3", 4711 } 
    }; 
}; 

QML:

ListView { 
    id: listView 
    anchors.fill: parent 
    model: MyListModel {} 

    delegate: Item { 
     implicitHeight: text.height 
     width: listView.width 
     Text { 
      id: text 
      text: model.heading + " " + model.description + " " + model.quantity 
     } 

     MouseArea { 
      anchors.fill: text 
      onClicked: { 
       model.quantity *= 2; 
      } 
     } 
    } 
}