I have the following TableView and was passed to QML via a C++ QAbstractTableModel and I want to make the cells editable pressing the enter key and after that the cells cannot be edited anymore. How can I achieve that? I have tried but nothing seem to work if I press enter.
Grid.cpp
#include "Grid.h"
Grid::Grid(QObject *parent) : QAbstractTableModel(parent)
{
int initialValues[9][9] = {
{7, 0, 2, 0, 5, 0, 6, 0, 0},
{0, 0, 0, 0, 0, 3, 0, 0, 0},
{1, 0, 0, 0, 0, 9, 5, 0, 0},
{8, 0, 0, 0, 0, 0, 0, 9, 0},
{0, 4, 3, 0, 0, 0, 7, 5, 0},
{0, 9, 0, 0, 0, 0, 0, 0, 8},
{0, 0, 9, 7, 0, 0, 0, 0, 5},
{0, 0, 0, 2, 0, 0, 0, 0, 0},
{0, 0, 7, 0, 4, 0, 2, 0, 3}
};
for (int row = 0; row < 9; ++row) {
for (int col = 0; col < 9; ++col) {
gridData[row][col] = initialValues[row][col];
}
}
}
int Grid::rowCount(const QModelIndex &) const
{
return 9;
}
int Grid::columnCount(const QModelIndex &) const
{
return 9;
}
QVariant Grid::data(const QModelIndex &index, int role) const
{
int row = index.row();
int col = index.column();
switch (role) {
case Qt::DisplayRole:
return gridData[row][col];
}
return QVariant();
}
bool Grid::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role == Qt::EditRole) {
if (!checkIndex(index))
return false;
gridData[index.row()][index.column()] = value.toInt();
return true;
}
return false;
}
Qt::ItemFlags Grid::flags(const QModelIndex &index) const
{
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}
QML file
TableView {
id: tableView
anchors.fill: parent
clip: true
model: SudokuGrid {}
delegate: Rectangle {
implicitWidth: 50
implicitHeight: 50
border {
color: "white"
width: 1
}
Rectangle {
width: 1
height: parent.height
color: model.column % 3 == 0 ? "black" : "transparent"
}
Rectangle {
width: parent.width
height: 1
color: model.row % 3 == 0 ? "black" : "transparent"
}
color: model.row % 2 ? "lightpink" : "lightblue"
Text {
anchors.centerIn: parent
text: display
font.pointSize: 12
}
TableView.editDelegate: TextField {
anchors.fill: parent
text: display
horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter
Component.onCompleted: selectAll()
onAccepted: {
tableView.commit()
}
TableView.onCommit: {
display = text
}
}
}
}
I tried to follow the documentation for TableView and add the same data function and the flags, but nothing seem to work
Visually, your Sudoku game is 2D, hence, why you think to use TableView and a 2D 9x9 array backend, however, with a simpler 1D model (with 81 values), you can solve it using a regular Repeater because the x,y coordinates of each Sudoku game cell can be present in your model (or derivable from your index). Your delegate can use those coordinates to place your delegate in a 2D arrangement.
The following snippet demonstrates how you may do this in QML:
You can Try it Online!