在QML / QT 5.7中添加和删除C ++列表中的项

时间:2017-01-12 15:59:03

标签: c++ qt qml qt5.7

我正在开发一个简单的项目来尝试学习QT 5.7,QML和C ++。我想创建一个简单的界面,其中包含一些项目列表,我可以使用几个按钮添加和删除项目。我一直在网上阅读一些不同的指南试图拼凑一些东西,但我一直陷入困境。我尝试过使用QQmlListProperty<T>QAbstractListModel,但我对这两种方法都有疑问:

  1. 我的项目QQmlListProperty<T>正确使用或我应该使用QAbstractListModel
  2. 对于这两种情况,如何通知我的QML视图列表已更改?
  3. 如果我使用QAbstractListModel&#39;,我是否只需要创建Q_INVOKABLE方法来添加和删除列表中的项目?
  4. 到目前为止,下面是QQmlListProperty<T>QAbstractListModel的代码。我已经省略了大部分类的实现,以保持这篇文章的简短,但如果需要实现,我很乐意添加它。

    QQmlListProperty项目类

    class PlaylistItemModel : public QObject
    {
            Q_OBJECT
            Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
        public:
            explicit PlaylistItemModel(QObject *parent = 0);
            QString getName();
            void setName(const QString &name);
    
        signals:
            void nameChanged();
    
        public slots:
    
        private:
            QString _name;
    };
    

    QQmlListProperty列表类

    class PlaylistModel : public QObject
    {
            Q_OBJECT
            Q_PROPERTY(QQmlListProperty<PlaylistItemModel> items READ getItems NOTIFY itemsChanged)
        public:
            explicit PlaylistModel(QObject *parent = 0);
            QQmlListProperty<PlaylistItemModel> getItems() const;
            Q_INVOKABLE void addItem(PlaylistItemModel *item);
            Q_INVOKABLE void removeItem(PlaylistItemModel *item);
            Q_INVOKABLE void clearItems();
    
            static void append(QQmlListProperty<PlaylistItemModel> *list, PlaylistItemModel *item);
            static PlaylistItemModel* at(QQmlListProperty<PlaylistItemModel> *list, int index);
            static int count(QQmlListProperty<PlaylistItemModel> *list);
            static void clear(QQmlListProperty<PlaylistItemModel> *list);
    
        signals:
            void itemsChanged();
    
        public slots:
    
        private:
            QList<PlaylistItemModel*> _items;
    };
    

    getItms()的实施:

    QQmlListProperty<PlaylistItemModel> PlaylistModel::getItems() const
    {
        return QQmlListProperty<PlaylistItemModel>(this, _items, &append, &count, &at, &clear);
    }
    

    QAbstractListModel

    class MyModel : public QAbstractListModel
    {
        Q_OBJECT
        public:
            enum ModelRoles
            {
                ItemRole = Qt::UserRole + 1
            };
    
            MyModel(QObject *parent = 0);
    
            // QAbstractItemModel interface
            int rowCount(const QModelIndex &parent) const;
            QVariant data(const QModelIndex &index, int role) const;
            QHash<int, QByteArray> roleNames() const;
    
        private:
            QList<QString> _listData;
            QString itemAt(const QModelIndex &index) const;
    };
    

1 个答案:

答案 0 :(得分:4)

我通常建议QAbstractListModel是大部分时间都适合的类,除非你确定你只使用一个简单的列表。

  

对于这两种情况,如何通知我的QML视图列表已更改?

QAbstractItemModel(QAbstractListModel继承)有许多不同的方法,您应该从子类调用这些方法来通知与其相关的视图已发生的事情。当您向其中插入项目时,您需要enter image description hereQAbstractItemModel::beginInsertRows

如果你的模型代表一些简单的东西,例如名字列表,你的插入可能看起来像这样:

假设:

class MyModel : public QAbstractListModel
{
public:
    Q_INVOKABLE void addPerson(const QString &name);
private:
    QVector<QString> m_names;
};

void MyModel::addPerson(const QString &name)
{
    beginInsertRows(QModelIndex(), m_names.count(), m_names.count());
    m_names.append(name);
    endInsertRows();
}

然后,您至少需要实施QAbstractItemModel::endInsertRowsQAbstractItemModel::rowCountQAbstractItemModel::roleNames,但看起来您已经处理好了。如果要实现数据编辑,还需要实现QAbstractItemModel::data

完成后,请注册该类型(使用qmlRegisterType):

qmlRegisterType<MyModel>("MyModelImport", 1, 0, "MyModel");

然后导入&amp;从QML中实例化它,并在您的视图中使用它:

import MyModelImport 1.0
import QtQuick 2.6

ListView {
    id: listView
    anchors.fill: parent
    model: MyModel {
    }
    delegate: TextInput {
        text: model.text
        onEditingFinished: {
            // when the text is edited, save it back to the model (which will invoke the saveData we overloaded)
            model.text = text
        }
    }

    Rectangle {
        height: 100
        width: 400
        color: "red"
        Text {
            text: "Add item"
        }
        MouseArea {
            anchors.fill: parent
            onClicked: listView.model.addName("Some new name")
        }
    }
}