I want to add to a QML table view a certain number of rows by pressing a button. The UI looks like this:
After pressing the "Update List Model" a new row should appear in the TableView.
My code looks like this (the bellow). I guess the addPerson
method has to emit a dataChanged event to get this working. How can I do this? Or is there a better solution to sync a QML table view with a C++ model?
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "MainWindow.h"
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
qmlRegisterType<TableModel>("TableModel", 0, 1, "TableModel");
QQmlApplicationEngine engine;
MainWindow mainWindow;
return app.exec();
}
MainWindow.h
#pragma once
#include <QQmlApplicationEngine>
#include <QtQuick>
#include "TableModel.h"
class MainWindow : public QObject {
Q_OBJECT;
public:
explicit MainWindow() {
engine_.load(QUrl(QStringLiteral("qrc:/main.qml")));
QObject *rootObject = engine_.rootObjects().first();
QObject::connect(rootObject, SIGNAL(on_ButtonUpdateListModel_click()), this, SLOT(on_ButtonUpdateListModel_click()));
}
public slots:
void on_ButtonUpdateListModel_click() {
QQuickView view;
QQmlContext *ctxt = view.rootContext();
model_.addPerson();
ctxt->setContextProperty("myModel", &model_);
}
private:
TableModel model_;
QQmlApplicationEngine engine_;
};
TableModel.h
#pragma once
#include <QAbstractTableModel>
#include <QObject>
class TableModel : public QAbstractTableModel {
Q_OBJECT;
enum TableRoles { TableDataRole = Qt::UserRole + 1, HeadingRole };
public:
explicit TableModel(QObject *parent = nullptr) : QAbstractTableModel(parent) {
table.append({
"First Name",
"Last Name",
"Age",
});
}
int rowCount(const QModelIndex & = QModelIndex()) const override {
return table.size();
}
int columnCount(const QModelIndex & = QModelIndex()) const override {
return table.at(0).size();
}
QVariant data(const QModelIndex &index, int role) const override {
switch (role) {
case TableDataRole: {
return table.at(index.row()).at(index.column());
}
case HeadingRole: {
if (index.row() == 0) {
return true;
} else {
return false;
}
}
default: break;
}
return QVariant();
}
QHash<int, QByteArray> roleNames() const override {
QHash<int, QByteArray> roles;
roles[TableDataRole] = "tabledata";
roles[HeadingRole] = "heading";
return roles;
}
void addPerson() {
table.append({
"Marc",
"Fonz",
"25",
});
int idx = table.size() - 1;
emit dataChanged(index(idx), index(idx));
}
private:
QVector<QVector<QString>> table;
};
main.qml
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import Qt.labs.settings 1.0
import Qt.labs.platform 1.0 as Platform
import QtQuick.Controls.Material 2.12
import TableModel 0.1
ApplicationWindow {
id: window
visible: true
width: 1040
height: 480
signal on_ButtonUpdateListModel_click()
ColumnLayout{
spacing: 2
anchors.fill: parent
Button {
text: qsTr("Update List Model")
onClicked: on_ButtonUpdateListModel_click()
}
TableModel {
id: myModel
}
TableView {
width: 400
height: 200
columnSpacing: 1
rowSpacing: 1
clip: true
ScrollIndicator.horizontal: ScrollIndicator { }
ScrollIndicator.vertical: ScrollIndicator { }
model: myModel
delegate: Rectangle {
implicitWidth: 100
implicitHeight: 20
border.color: "black"
border.width: 2
color: (heading==true) ? 'teal':"green"
TableView.onPooled: console.log(tabledata + " pooled")
TableView.onReused: console.log(tabledata + " resused")
Text {
text: tabledata
font.pointSize: 10
anchors.centerIn: parent
}
}
}
}
}