Simple table model. I'm trying to update one cell via spinbox. But the index passed is perceived as a number:
TypeError: descriptor 'index' for '...QAbstractTableModel' objects doesn't apply to a 'int' object.
See the __handleSpinBox
method at the bottom of the code. I tried to manipulate the method setData
but nothing worked out. Another odd thing is that there is almost nothing about this error in Google search.
from PySide6.QtCore import *
from PySide6.QtWidgets import QWidget, QHBoxLayout, QTableView, QApplication, QAbstractItemView, QSpinBox
from PySide6.QtGui import *
import sys
import numpy as np
import pandas as pd
import copy
class PandasModel(QAbstractTableModel):
def __init__(self, table):
super(PandasModel, self).__init__()
data = pd.DataFrame(table)
self._data = data
def rowCount(self, parent=None):
return self._data.shape[0]
def columnCount(self, parent=None):
return self._data.shape[1]
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
if role == Qt.DisplayRole or role == Qt.EditRole:
return str(self._data.iloc[index.row(), index.column()])
return None
def setData(self, index, value, role: Qt.EditRole):
if not index.isValid():
return False
if role == Qt.EditRole:
row = index.row()
column = index.column()
self._data[row][column] = value
self.dataChanged.emit(index)
return True
return False
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._data.columns[col]
return None
class MyTable(QTableView):
def __init__(self, model:QAbstractTableModel, data, parent=None):
super().__init__(parent)
self.data = data
self.horizontalHeader().setVisible(True)
self.verticalHeader().setVisible(False)
self.model = model(pd.DataFrame(data, columns=['Col1', 'Col2', 'Col3']))
self.setModel(self.model)
class MainWidget(QWidget):
def __init__(self):
super().__init__()
self.spinBox = QSpinBox()
self.spinBox.setRange(-100, 100)
self.spinBox.setValue(0)
self.spinBox.valueChanged.connect(self.__handleSpinBox)
self.pandasModel = PandasModel
table = MyTable(PandasModel, [[0,0,0], [0,0,0]])
hbox = QHBoxLayout()
hbox.addWidget(self.spinBox, 1)
hbox.addWidget(table, 1)
self.setLayout(hbox)
def __handleSpinBox(self, value):
self.pandasModel.setData(self.pandasModel.index(1,1), result, Qt.EditRole) #TypeError:
# descriptor 'index' for 'PySide6.QtCore.QAbstractTableModel' objects doesn't apply to a 'int' object
if __name__ == '__main__':
app = QApplication(sys.argv)
MW = MainWidget()
MW.show()
sys.exit(app.exec())
There are reasons to define QTableView in a separate class. Only one cell changes (1,1).
from PySide6.QtCore import *
from PySide6.QtWidgets import QWidget, QHBoxLayout, QTableView, Application, QAbstractItemView, QSpinBox
from PySide6.QtGui import *
import sys
import pandas as pd
externalData = [[0,0,0], [0,0,0], [0,0,0]]
class PandasModel(QAbstractTableModel):
def __init__(self, data):
super(PandasModel, self).__init__()
self._data = pd.DataFrame(data, columns=['Col1', 'Col2', 'Col3'])
def rowCount(self, parent=None):
return self._data.shape[0]
def columnCount(self, parent=None):
return self._data.shape[1]
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
if role == Qt.DisplayRole or role == Qt.EditRole:
return str(self._data.iloc[index.row(), index.column()])
return None
def setData(self, index, value, role: Qt.EditRole):
if role == Qt.EditRole:
self._data.iat[index.row(), index.column()] = value
return True
return False
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._data.columns[col]
return None
class MyTable(QTableView):
def __init__(self):
super(MyTable, self).__init__()
self.horizontalHeader().setVisible(True)
self.verticalHeader().setVisible(False)
class MainWidget(QWidget):
def __init__(self, data):
super().__init__()
self.resize(500,200)
self.data = data
self.spinBox = QSpinBox()
self.spinBox.setRange(-100, 100)
self.spinBox.setValue(0)
self.spinBox.valueChanged.connect(self.__handleSpinBox)
self.model = PandasModel(self.data)
self.table = MyTable()
self.table.setModel(self.model)
hbox = QHBoxLayout()
hbox.addWidget(self.spinBox, 1)
hbox.addWidget(self.table, 3)
self.setLayout(hbox)
def __handleSpinBox(self, value):
self.model.setData(self.model.index(1, 1), value, Qt.EditRole)
self.model.dataChanged.connect(self.table.update(self.model.index(1, 1)))
if __name__ == '__main__':
app = QApplication(sys.argv)
MW = MainWidget(externalData)
MW.show()
sys.exit(app.exec())```