QML QAbstractItemModel: как вставить в индекс i

Я использую Qt example forQAbstractItemModel и пытаюсь добавить Item к данному index.

Я прочитал документ и пытаюсь использовать это

Но он работает не так, как ожидалось, и вместо добавления new Item он просто копирует уже существующий элемент.

Вот пример:

Что я хочу: когда вы нажимаете кнопку, она вставляет в индекс 2 новое животное под названием Лев. >'. Но вместо этого он вставляет уже существующее животное. Для этого предназначена функция test().

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

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() {

    beginInsertRows(QModelIndex(), 2, 2);
    m_animals.append(Animal("Lion", "Large"));
    endInsertRows();

 }

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

У вас есть идеи, почему это не работает? Большое спасибо !


person Ed Nio    schedule 19.04.2017    source источник


Ответы (1)


Я предполагаю, что проблема заключается в строке, в которой вы фактически добавили данные в модель:

m_animals.append(Animal("Lion", "Large"));

вы просто добавляете его к QList<Animal> m_animals; вместо того, чтобы вставлять его в правильный индекс!?

m_animals.insert(2, Animal("Lion", "Large"));

поэтому данные модели существенно повреждены и данные не копируются, а вставляются не в то место.

person xander    schedule 19.04.2017
comment
Хорошо, я думал, что порядок данных модели не проблема для представления. Большое спасибо за ответ ! - person Ed Nio; 19.04.2017
comment
Почему m_animals.insert(2, Animal("Lion", "Large")); неверно? doc.qt.io/qt-5/qlist.html#insert И, конечно, важен порядок, представление просто отображает модель QList, и если вы скажете, что индекс представления 2 изменился, он обновит только этот индекс, а не весь список, поэтому кажется, что данные копируются в представлении, потому что значение в индексе 2 вообще не изменилось. - person xander; 19.04.2017
comment
Я отредактировал свой ответ, вы были в порядке! :) Спасибо еще раз - person Ed Nio; 19.04.2017