2014-02-17 48 views
5

我已經想出如何將從QAbstractListModel派生的模型綁定到QML視圖。QML視圖在向QAbstractListModel模型添加新項時不會更新

但是,我累了的下一件事是行不通的。如果新模型添加到模型中,QML視圖將不會更新。這是爲什麼?

DataObject.h

class DataObject { 
    public: 
     DataObject(const QString &firstName, 
        const QString &lastName): 
      first(firstName), 
      last(lastName) {} 

     QString first; 
     QString last; 
}; 

SimpleListModel.h

class SimpleListModel : public QAbstractListModel 
{ 
    Q_OBJECT 

    enum /*class*/ Roles { 
     FIRST_NAME = Qt::UserRole, 
     LAST_NAME 
    }; 

    public: 
     SimpleListModel(QObject *parent=0); 
     QVariant data(const QModelIndex &index, int role) const; 
     Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const; 
     QHash<int, QByteArray> roleNames() const; 
     void addName(QString firstName, QString lastName); 

    private: 
     Q_DISABLE_COPY(SimpleListModel); 
     QList<DataObject*> m_items; 
}; 

SimpleListModel.cpp

SimpleListModel::SimpleListModel(QObject *parent) : 
    QAbstractListModel(parent) 
{ 
    DataObject *first = new DataObject(QString("Firstname01"), QString("Lastname01")); 
    DataObject *second = new DataObject(QString("Firstname02"), QString("Lastname02")); 
    DataObject *third = new DataObject(QString("Firstname03"), QString("Lastname03")); 

    m_items.append(first); 
    m_items.append(second); 
    m_items.append(third); 
} 

QHash<int, QByteArray> SimpleListModel::roleNames() const 
{ 
    QHash<int, QByteArray> roles; 

    roles[/*Roles::*/FIRST_NAME] = "firstName"; 
    roles[/*Roles::*/LAST_NAME] = "lastName"; 

    return roles; 
} 

void SimpleListModel::addName(QString firstName, QString lastName) 
{ 
    DataObject *dataObject = new DataObject(firstName, lastName); 

    m_items.append(dataObject); 

    emit dataChanged(this->index(m_items.size()), this->index(m_items.size())); 
} 

int SimpleListModel::rowCount(const QModelIndex &) const 
{ 
    return m_items.size(); 
} 

QVariant SimpleListModel::data(const QModelIndex &index, int role) const 
{ 
    //--- Return Null variant if index is invalid 
    if(!index.isValid()) 
     return QVariant(); 

    //--- Check bounds 
    if(index.row() > (m_items.size() - 1)) 
     return QVariant(); 

    DataObject *dobj = m_items.at(index.row()); 

    switch (role) 
    { 
     case /*Roles::*/FIRST_NAME: 
      return QVariant::fromValue(dobj->first); 

     case /*Roles::*/LAST_NAME: 
      return QVariant::fromValue(dobj->last); 

     default: 
      return QVariant(); 
    } 
} 

AppCore.h

class AppCore : public QObject 
{ 
    Q_OBJECT 
    Q_PROPERTY(SimpleListModel *simpleListModel READ simpleListModel CONSTANT) 

    public: 
     explicit AppCore(QObject *parent = 0); 
     SimpleListModel *simpleListModel() const; 

    public slots: 
     void addName(); 

    private: 
     SimpleListModel *m_SimpleListModel; 

}; 

AppCore.cpp

AppCore::AppCore(QObject *parent) : 
    QObject(parent) 
{ 
    m_SimpleListModel = new SimpleListModel(this); 
} 

SimpleListModel *AppCore::simpleListModel() const 
{ 
    return m_SimpleListModel; 
} 

void AppCore::addName() 
{ 
    m_SimpleListModel->addName("FirstnameNEW", "LastnameNEW"); 
} 

的main.cpp

int main(int argc, char *argv[]) 
{ 
    QGuiApplication a(argc, argv); 

    QQuickView *view = new QQuickView(); 
    AppCore *appCore = new AppCore(); 

    qRegisterMetaType<SimpleListModel *>("SimpleListModel"); 

    view->engine()->rootContext()->setContextProperty("appCore", appCore); 
    view->setSource(QUrl::fromLocalFile("main.qml")); 
    view->show(); 

    return a.exec(); 
} 

main.qml

// ... 
ListView { 
    id: myListView 
    anchors.fill: parent 
    delegate: myDelegate 
    model: appCore.simpleListModel 
} 

MouseArea { 
    anchors.fill: parent 
    onClicked: { 
     appCore.addName() 
     console.log('rowCount: ' + appCore.simpleListModel.rowCount()) 
    } 
} 
//... 

回答

10

你應該調用beginInsertRows和endInsertRows代替發射信號

void SimpleListModel::addName(QString firstName, QString lastName) 
{ 
    DataObject *dataObject = new DataObject(firstName, lastName); 

    // tell QT what you will be doing 
    beginInsertRows(ModelIndex(),m_items.size(),m_items.size()); 

    // do it 
    m_items.append(dataObject); 

    // tell QT you are done 
    endInsertRows(); 

} 

的這兩個功能上發射所需的所有信號

1

你忽略了一個QAbstractItemModel的語義。有兩種類型的信號,一個模型必須發出:

  • 數據變化的信號:它們必須發出後的數據被改變。數據變化是現有項目價值的變化。對模型的其他更改是而不是稱爲數據更改 - 這裏的術語具有特定含義。

  • 結構變化的信號:它們必須和之前任何結構變化後射出。結構變化是添加或刪除任何項目。幫助功能beginXxxYyyendXxxYyy發出這些信號。

相關問題