我正在开发一个简单的项目来尝试学习QT 5.7,QML和C ++。我想创建一个简单的界面,其中包含一些项目列表,我可以使用几个按钮添加和删除项目。我一直在网上阅读一些不同的指南试图拼凑一些东西,但我一直陷入困境。我尝试过使用QQmlListProperty<T>
和QAbstractListModel
,但我对这两种方法都有疑问:
QQmlListProperty<T>
正确使用或我应该使用QAbstractListModel
?Q_INVOKABLE
方法来添加和删除列表中的项目?到目前为止,下面是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;
};
答案 0 :(得分:4)
我通常建议QAbstractListModel是大部分时间都适合的类,除非你确定你只使用一个简单的列表。
对于这两种情况,如何通知我的QML视图列表已更改?
QAbstractItemModel(QAbstractListModel继承)有许多不同的方法,您应该从子类调用这些方法来通知与其相关的视图已发生的事情。当您向其中插入项目时,您需要和QAbstractItemModel::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::endInsertRows,QAbstractItemModel::rowCount和QAbstractItemModel::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")
}
}
}