下面的代码对我来说很好。您的问题可能在其他地方。由于使用了 Qt Quick Controls,这是针对 Qt 5 的。
有两个视图访问同一个模型,这在视觉上确认模型发出适当的信号以通知视图更改。页面添加和删除是通过标准insertRows
和removeRows
方法完成的,通过Q_INVOKABLE
. 到目前为止,此模型上不需要任何自定义方法。这Q_INVOKABLE
是 QML 和QAbstractItemModel
.
主文件
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QAbstractListModel>
#include <QQmlContext>
#include <QtQml>
class GPage : public QObject {
Q_OBJECT
Q_PROPERTY(QString name NOTIFY nameChanged MEMBER m_name)
Q_PROPERTY(int number NOTIFY numberChanged MEMBER m_number)
QString m_name;
int m_number;
public:
GPage(QObject * parent = 0) : QObject(parent), m_number(0) {}
GPage(QString name, int number, QObject * parent = 0) :
QObject(parent), m_name(name), m_number(number) {}
Q_SIGNAL void nameChanged(const QString &);
Q_SIGNAL void numberChanged(int);
};
class PageModel : public QAbstractListModel {
Q_OBJECT
QList<GPage*> m_pageList;
public:
PageModel(QObject * parent = 0) : QAbstractListModel(parent) {}
~PageModel() { qDeleteAll(m_pageList); }
int rowCount(const QModelIndex &) const Q_DECL_OVERRIDE {
return m_pageList.count();
}
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE {
if (role == Qt::DisplayRole || role == Qt::EditRole) {
return QVariant::fromValue<QObject*>(m_pageList.at(index.row()));
}
return QVariant();
}
bool setData(const QModelIndex &index, const QVariant &value, int role) Q_DECL_OVERRIDE {
Q_UNUSED(role);
GPage* page = value.value<GPage*>();
if (!page) return false;
if (page == m_pageList.at(index.row())) return true;
delete m_pageList.at(index.row());
m_pageList[index.row()] = page;
QVector<int> roles;
roles << role;
emit dataChanged(index, index, roles);
return true;
}
Q_INVOKABLE bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE {
Q_UNUSED(parent);
beginInsertRows(QModelIndex(), row, row + count - 1);
for (int i = row; i < row + count; ++ i) {
QString const name = QString("Page %1").arg(i + 1);
GPage * page = new GPage(name, i + 1, this);
m_pageList.insert(i, page);
QQmlEngine::setObjectOwnership(page, QQmlEngine::CppOwnership);
}
endInsertRows();
return true;
}
Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE {
Q_UNUSED(parent);
beginRemoveRows(QModelIndex(), row, row + count - 1);
while (count--) delete m_pageList.takeAt(row);
endRemoveRows();
return true;
}
};
int main(int argc, char *argv[])
{
PageModel model1;
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
model1.insertRows(0, 1);
engine.rootContext()->setContextProperty("model1", &model1);
qmlRegisterType<GPage>();
engine.load(QUrl("qrc:/main.qml"));
QObject *topLevel = engine.rootObjects().value(0);
QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
window->show();
return app.exec();
}
#include "main.moc"
main.qml
import QtQuick 2.0
import QtQml.Models 2.1
import QtQuick.Controls 1.0
ApplicationWindow {
width: 300; height: 300
Row {
width: parent.width
anchors.top: parent.top
anchors.bottom: column.top
Component {
id: commonDelegate
Rectangle {
width: view.width
implicitHeight: editor.implicitHeight + 10
color: "transparent"
border.color: "red"
border.width: 2
radius: 5
TextInput {
id: editor
anchors.margins: 1.5 * parent.border.width
anchors.fill: parent
text: edit.name // "edit" role of the model, to break the binding loop
onTextChanged: {
display.name = text;
model.display = display
}
}
}
}
ListView {
id: view
width: parent.width / 2
height: parent.height
model: DelegateModel {
id: delegateModel1
model: model1
delegate: commonDelegate
}
spacing: 2
}
ListView {
width: parent.width / 2
height: parent.height
model: DelegateModel {
model: model1
delegate: commonDelegate
}
spacing: 2
}
}
Column {
id: column;
anchors.bottom: parent.bottom
Row {
Button {
text: "Add Page";
onClicked: model1.insertRows(delegateModel1.count, 1)
}
Button {
text: "Remove Page";
onClicked: model1.removeRows(pageNo.value - 1, 1)
}
SpinBox {
id: pageNo
minimumValue: 1
maximumValue: delegateModel1.count;
}
}
}
}
主.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>