Skip to content Skip to sidebar Skip to footer

Adding Row To Qtableview With Model And And Delegate Widgets

I am trying to add a row to QTableView with a QAbstractTableModel and QItemDelegate where the widgets appear in the added row. From what I've read I need to call .edit(index) on ea

Solution 1:

First of all, you could use openPersistentEditor as you already did in the __init__.

There are two reasons for the error in self.table.edit():

  1. in order to allow editing of an item through edit(), the flags() function must be overridden and provide the Qt.ItemIsEditable flag;
  2. you cannot call edit() multiple times on different indexes within the same function;

Then, there are other important problems in your code:

  • you're not correctly using the model, as data() is not implemented;
  • the delegates should use the base functions of the model whenever they provide standard behavior (accessing index.model()._data is not good);
  • setEditorData is unnecessary, as long as the above aspects are respected: Qt automatically sets the data based on the data type and the editor class;
  • setData() should be implemented in order to correctly set the data on the model, otherwise the new data won't be accessible;
  • changes in the model structure (like creating a new row) should be done in the model class;

Here is a revised version of your code:

class Delegate(QItemDelegate):
    def __init__(self):
        QItemDelegate.__init__(self)
        self.type_items = ["1", "2", "3"]

    def createEditor(self, parent, option, index):
        if index.column() == 0:
            comboBox = QComboBox(parent)
            for text in self.type_items:
                comboBox.addItem(text, (index.row(), index.column()))
            return comboBox
        # no need to check for the other columns, as Qt automatically creates a
        # QLineEdit for string values and QTimeEdit for QTime values;
        return super().createEditor(parent, option, index)

    # no setEditorData() required


class TableModel(QAbstractTableModel):
    def __init__(self, data):
        super(TableModel, self).__init__()
        self._data = data

    def appendRowData(self, data):
        self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
        self._data.append(data)
        self.endInsertRows()

    def data(self, index, role=Qt.DisplayRole):
        if role in (Qt.DisplayRole, Qt.EditRole):
            return self._data[index.row()][index.column()]

    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole:
            self._data[index.row()][index.column()] = value
            self.dataChanged.emit(index, index)
            return True
        return False

    def rowCount(self, index=None):
        return len(self._data)

    def columnCount(self, index=None):
        return len(self._data[0])

    def flags(self, index):
        # allow editing of the index
        return super().flags(index) | Qt.ItemIsEditable


class MainWindow(QMainWindow):
    # ...
    def addRow(self):
        row = self.model.rowCount()

        new_row_data = ["3", "Howdy", QTime(9, 0)]
        self.model.appendRowData(new_row_data)

        for i in range(self.model.columnCount()):
            index = self.model.index(row, i)
            self.table.openPersistentEditor(index)

Post a Comment for "Adding Row To Qtableview With Model And And Delegate Widgets"