在 QML/QT 5.7 中添加和删除 C++ 列表中的项目
Adding and removing items from a C++ list in QML/QT 5.7
我正在做一个简单的项目来尝试学习 QT 5.7、QML 和 C++。我想创建一个简单的界面,其中包含一个项目列表,我可以使用几个按钮添加和删除项目。我一直在网上阅读一堆不同的指南,试图拼凑一些东西,但我一直被卡住了。我试过使用 QQmlListProperty<T>
和 QAbstractListModel
但我对这两种方法都有疑问:
- 对于我的项目来说
QQmlListProperty<T>
是正确的选择还是我应该使用 QAbstractListModel
?
- 无论哪种情况,我如何通知我的 QML 视图列表已更改?
- 如果我使用 'QAbstractListModel',是否只需要创建
Q_INVOKABLE
方法来添加和删除列表中的项目?
下面是我目前针对 QQmlListProperty<T>
和 QAbstractListModel
的代码。我省略了 类 的大部分实现以保持此 post 简短,但如果需要实现,我很乐意添加它。
QQmlListProperty
项目 Class
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
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;
};
我通常会建议 QAbstractListModel 在大多数情况下是正确的 class,除非您确定您只会使用一个简单的列表。
For either case how do I notify my QML view that the list has changed?
QAbstractItemModel(QAbstractListModel 继承)有许多不同的方法,您应该从您的 subclass 调用这些方法以通知与其连接的视图发生了某些事情。当您向其中插入项目时,您需要 QAbstractItemModel::beginInsertRows and QAbstractItemModel::endInsertRows.
如果您的模型代表的是一些简单的东西,例如姓名列表,您的插入可能看起来像这样:
假设:
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::rowCount, QAbstractItemModel::roleNames, and QAbstractItemModel::data at a minimum, but it looks like you've already got that handled. If you want to implement editing of data, you also want to implement QAbstractListModel::setData。
完成后,注册类型(使用 qmlRegisterType):
qmlRegisterType<MyModel>("MyModelImport", 1, 0, "MyModel");
然后从 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")
}
}
}
我正在做一个简单的项目来尝试学习 QT 5.7、QML 和 C++。我想创建一个简单的界面,其中包含一个项目列表,我可以使用几个按钮添加和删除项目。我一直在网上阅读一堆不同的指南,试图拼凑一些东西,但我一直被卡住了。我试过使用 QQmlListProperty<T>
和 QAbstractListModel
但我对这两种方法都有疑问:
- 对于我的项目来说
QQmlListProperty<T>
是正确的选择还是我应该使用QAbstractListModel
? - 无论哪种情况,我如何通知我的 QML 视图列表已更改?
- 如果我使用 'QAbstractListModel',是否只需要创建
Q_INVOKABLE
方法来添加和删除列表中的项目?
下面是我目前针对 QQmlListProperty<T>
和 QAbstractListModel
的代码。我省略了 类 的大部分实现以保持此 post 简短,但如果需要实现,我很乐意添加它。
QQmlListProperty
项目 Class
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
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;
};
我通常会建议 QAbstractListModel 在大多数情况下是正确的 class,除非您确定您只会使用一个简单的列表。
For either case how do I notify my QML view that the list has changed?
QAbstractItemModel(QAbstractListModel 继承)有许多不同的方法,您应该从您的 subclass 调用这些方法以通知与其连接的视图发生了某些事情。当您向其中插入项目时,您需要 QAbstractItemModel::beginInsertRows and QAbstractItemModel::endInsertRows.
如果您的模型代表的是一些简单的东西,例如姓名列表,您的插入可能看起来像这样:
假设:
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::rowCount, QAbstractItemModel::roleNames, and QAbstractItemModel::data at a minimum, but it looks like you've already got that handled. If you want to implement editing of data, you also want to implement QAbstractListModel::setData。
完成后,注册类型(使用 qmlRegisterType):
qmlRegisterType<MyModel>("MyModelImport", 1, 0, "MyModel");
然后从 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")
}
}
}