2017-04-19 525 views
2

我使用Qt example for QAbstractItemModel,我尝试将Item更新为给定的index如何在数据更新时更新QAbstractItemModel视图

我试过使用emit DataChanged但它不起作用,视图没有更新

下面是一个例子:

我想要什么:当你点击按钮,它会在索引0,动物的type更新数据将会改变,这将成为一个狮子

#include <QAbstractListModel> 
#include <QStringList> 
#include <qqmlcontext.h> 
//![0] 
class Animal 
{ 
public: 
    Animal(const QString &type, const QString &size); 
//![0] 

    QString type() const; 
    QString size() const; 

    void setType(QString q) { 
     m_type = q; 
    } 

private: 
    QString m_type; 
    QString m_size; 
//![1] 
}; 

class AnimalModel : public QAbstractListModel 
{ 
    Q_OBJECT 
public: 

    Q_INVOKABLE void test() ; 
    void setName(const QString &name); 
    enum AnimalRoles { 
     TypeRole = Qt::UserRole + 1, 
     SizeRole 
    }; 

    AnimalModel(QObject *parent = 0); 
//![1] 
//! 
//! 
    void setContext(QQmlContext *ctx) { 
     m_ctx = ctx; 
    } 

    void addAnimal(const Animal &animal); 

    int rowCount(const QModelIndex & parent = QModelIndex()) const; 

    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; 
    QHash<int, QByteArray> roleNames() const; 

protected: 

private: 
    QList<Animal> m_animals; 
    QQmlContext* m_ctx; 

signals: 
    void dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight); 
//![2] 
}; 
//![2] 

model.h

#include "model.h" 
#include "qDebug" 
Animal::Animal(const QString &type, const QString &size) 
    : m_type(type), m_size(size) 
{ 
} 

QString Animal::type() const 
{ 
    return m_type; 
} 

QString Animal::size() const 
{ 
    return m_size; 
} 




AnimalModel::AnimalModel(QObject *parent) 
    : QAbstractListModel(parent) 
{ 
} 

void AnimalModel::addAnimal(const Animal &animal) 
{ 
    beginInsertRows(QModelIndex(), rowCount(), rowCount()); 
    m_animals << animal; 
    endInsertRows(); 
} 

void AnimalModel::test() { 

    m_animals[0].setType("Lion"); 
    emit dataChanged(QModelIndex(),QModelIndex()); 

    //I also tried: 
    QModelIndex topLeft = createIndex(0,0); 
    emit dataChanged(topLeft, topLeft); 


} 

int AnimalModel::rowCount(const QModelIndex & parent) const { 
    Q_UNUSED(parent); 
    return m_animals.count(); 
} 

QVariant AnimalModel::data(const QModelIndex & index, int role) const { 
    if (index.row() < 0 || index.row() >= m_animals.count()) 
     return QVariant(); 

    const Animal &animal = m_animals[index.row()]; 
    if (role == TypeRole) 
     return animal.type(); 
    else if (role == SizeRole) 
     return animal.size(); 
    return QVariant(); 
} 

//![0] 
QHash<int, QByteArray> AnimalModel::roleNames() const { 
    QHash<int, QByteArray> roles; 
    roles[TypeRole] = "type"; 
    roles[SizeRole] = "size"; 
    return roles; 
} 
//![0] 

model.cpp

#include "model.h" 

#include <QGuiApplication> 
#include <qqmlengine.h> 
#include <qqmlcontext.h> 
#include <qqml.h> 
#include <QtQuick/qquickitem.h> 
#include <QtQuick/qquickview.h> 

//![0] 
int main(int argc, char ** argv) 
{ 
    QGuiApplication app(argc, argv); 

    AnimalModel model; 
    model.addAnimal(Animal("Wolf", "Medium")); 
    model.addAnimal(Animal("Polar bear", "Large")); 
    model.addAnimal(Animal("Quoll", "Small")); 

    QQuickView view; 
    view.setResizeMode(QQuickView::SizeRootObjectToView); 
    QQmlContext *ctxt = view.rootContext(); 
    ctxt->setContextProperty("myModel", &model); 
//![0] 

    view.setSource(QUrl("qrc:view.qml")); 


    view.show(); 

    return app.exec(); 
} 

main.cpp中

import QtQuick 2.0 
import QtQuick 2.4 
import QtQuick.Controls 1.3 
import QtQuick.Window 2.2 
import QtQuick.Dialogs 1.2 
import QtQuick.Layouts 1.2 
import QtQml.Models 2.1 
import QtQuick.Controls.Styles 1.2 


//![0] 
ListView { 
    width: 200; height: 250 

    model: myModel 
    delegate: Text { text: "Animal: " + type + ", " + size } 

    MouseArea { 
     anchors.fill: parent 
     cursorShape: Qt.PointingHandCursor 
     onClicked: { 

     } 
    } 
    Button { 
     anchors.bottom: parent.bottom 
     width:50; height:50 
     text:"click" 
     onClicked: { 
      myModel.test() 
     } 

    } 

} 
//![0] 

View.qml

你有任何想法,为什么它不工作? 非常感谢!

+0

你试过来实现与记录的签名'dataChanged'信号:http://doc.qt.io/qt-5/qabstractitemmodel.html#dataChanged? – derM

+0

你好,我第一次尝试的是在这种情况下写''emit dataChanged(0,0)'',因为第一个'data'已经更新。但dataChanged不接受'int',并且我在这里写的东西有点遗失,因为我不能写'QModelIndex(0)'这样的东西。这可能是愚蠢的东西,但我真的是这样的概念的新手。 –

+0

我也试过'QModelIndex topLeft = createIndex(0,0); emit dataChanged(topLeft,topLeft);' –

回答

2

不要在子类中重新定义信号。

删除以下行(在model.h),并预期它应该工作:

signals: 
    void dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight); 

而且这个调用dataChanged()时,你必须指定一个有效的QModelIndex。这是正确的:

// I also tried: 
    QModelIndex topLeft = createIndex(0,0); 
    emit dataChanged(topLeft, topLeft); 
+2

或'emit QAbstractListModel :: dataChanged(index(0),index(0)); ' – derM

+0

谢谢你们两位! –