当模型为 pandas 数据框时使 QTableView 可编辑
Make QTableView editable when model is pandas dataframe
在我的gui文件中我创建了一个QTableView如下(这是Qt Designer自动生成的部分):
self.pnl_results = QtGui.QTableView(self.tab_3)
font = QtGui.QFont()
font.setPointSize(7)
self.pnl_results.setFont(font)
self.pnl_results.setFrameShape(QtGui.QFrame.StyledPanel)
self.pnl_results.setFrameShadow(QtGui.QFrame.Sunken)
self.pnl_results.setEditTriggers(QtGui.QAbstractItemView.AllEditTriggers)
self.pnl_results.setShowGrid(True)
self.pnl_results.setSortingEnabled(True)
self.pnl_results.setCornerButtonEnabled(True)
self.pnl_results.setObjectName("pnl_results")
然后我定义了一个模型,使我能够 link QTableView 的 pandas 数据框:
class PandasModel(QtCore.QAbstractTableModel):
"""
Class to populate a table view with a pandas dataframe
"""
def __init__(self, data, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self._data = data
def rowCount(self, parent=None):
return len(self._data.values)
def columnCount(self, parent=None):
return self._data.columns.size
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid():
if role == QtCore.Qt.DisplayRole:
return str(self._data.values[index.row()][index.column()])
return None
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self._data.columns[col]
return None
def setData(self, index, value, role):
if not index.isValid():
return False
if role != QtCore.Qt.EditRole:
return False
row = index.row()
if row < 0 or row >= len(self._data.values):
return False
column = index.column()
if column < 0 or column >= self._data.columns.size:
return False
self._data.values[row][column] = value
self.dataChanged.emit(index, index)
return True
def flags(self, index):
flags = super(self.__class__,self).flags(index)
flags |= QtCore.Qt.ItemIsEditable
flags |= QtCore.Qt.ItemIsSelectable
flags |= QtCore.Qt.ItemIsEnabled
flags |= QtCore.Qt.ItemIsDragEnabled
flags |= QtCore.Qt.ItemIsDropEnabled
return flags
最后将我的 pandas 数据框 (df) 添加到模型中:
model = PandasModel(df)
self.ui.pnl_results.setModel(model)
这在 QTableView 中正确显示了我的 pandas 数据框。但是,出于某种原因,当我将 return 编辑为它们的原始值时(并且一旦我编辑该字段,它开始为空)。如何使其可编辑,然后将结果写回 pandas 数据框?
您的模型缺少 setData 方法。 QtCore.QAbstractTableModel
的默认实现什么也不做,returns False
。您需要在您的模型中实现此方法以使其项目可编辑。如果 df
是存储数据的实际容器,您应该简单地在 setData
方法中更改存储在容器中的项目的值。它可能看起来像这样:
def setData(self, index, value, role):
if not index.isValid():
return False
if role != QtCore.Qt.EditRole:
return False
row = index.row()
if row < 0 or row >= len(self._data.values):
return False
column = index.column()
if column < 0 or column >= self._data.columns.size:
return False
self._data.values[row][column] = value
self.dataChanged.emit(index, index)
return True
您还需要对 return 包含 QtCore.Qt.ItemIsEditable
.
的值实施 flags 方法
在我的gui文件中我创建了一个QTableView如下(这是Qt Designer自动生成的部分):
self.pnl_results = QtGui.QTableView(self.tab_3)
font = QtGui.QFont()
font.setPointSize(7)
self.pnl_results.setFont(font)
self.pnl_results.setFrameShape(QtGui.QFrame.StyledPanel)
self.pnl_results.setFrameShadow(QtGui.QFrame.Sunken)
self.pnl_results.setEditTriggers(QtGui.QAbstractItemView.AllEditTriggers)
self.pnl_results.setShowGrid(True)
self.pnl_results.setSortingEnabled(True)
self.pnl_results.setCornerButtonEnabled(True)
self.pnl_results.setObjectName("pnl_results")
然后我定义了一个模型,使我能够 link QTableView 的 pandas 数据框:
class PandasModel(QtCore.QAbstractTableModel):
"""
Class to populate a table view with a pandas dataframe
"""
def __init__(self, data, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self._data = data
def rowCount(self, parent=None):
return len(self._data.values)
def columnCount(self, parent=None):
return self._data.columns.size
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid():
if role == QtCore.Qt.DisplayRole:
return str(self._data.values[index.row()][index.column()])
return None
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self._data.columns[col]
return None
def setData(self, index, value, role):
if not index.isValid():
return False
if role != QtCore.Qt.EditRole:
return False
row = index.row()
if row < 0 or row >= len(self._data.values):
return False
column = index.column()
if column < 0 or column >= self._data.columns.size:
return False
self._data.values[row][column] = value
self.dataChanged.emit(index, index)
return True
def flags(self, index):
flags = super(self.__class__,self).flags(index)
flags |= QtCore.Qt.ItemIsEditable
flags |= QtCore.Qt.ItemIsSelectable
flags |= QtCore.Qt.ItemIsEnabled
flags |= QtCore.Qt.ItemIsDragEnabled
flags |= QtCore.Qt.ItemIsDropEnabled
return flags
最后将我的 pandas 数据框 (df) 添加到模型中:
model = PandasModel(df)
self.ui.pnl_results.setModel(model)
这在 QTableView 中正确显示了我的 pandas 数据框。但是,出于某种原因,当我将 return 编辑为它们的原始值时(并且一旦我编辑该字段,它开始为空)。如何使其可编辑,然后将结果写回 pandas 数据框?
您的模型缺少 setData 方法。 QtCore.QAbstractTableModel
的默认实现什么也不做,returns False
。您需要在您的模型中实现此方法以使其项目可编辑。如果 df
是存储数据的实际容器,您应该简单地在 setData
方法中更改存储在容器中的项目的值。它可能看起来像这样:
def setData(self, index, value, role):
if not index.isValid():
return False
if role != QtCore.Qt.EditRole:
return False
row = index.row()
if row < 0 or row >= len(self._data.values):
return False
column = index.column()
if column < 0 or column >= self._data.columns.size:
return False
self._data.values[row][column] = value
self.dataChanged.emit(index, index)
return True
您还需要对 return 包含 QtCore.Qt.ItemIsEditable
.