我想在PyQt表中显示一个pandas数据帧。我已经取得了一些进展,但是无法正确派生Table Model类。对此有任何帮助将非常感激。
**请注意完整示例代码here **
我正在努力生成有效的QtCore.QAbstractTableModel派生类。继上一个关于QItemDelegates的问题后,我试图从Pandas DataFrame生成一个表模型来插入实际数据。我有工作示例代码here,但是如果我在Widget类(ln 152)中用TableModel2替换我的TableModel,我就无法显示该表。
class TableModel2(QtCore.QAbstractTableModel):
def __init__(self, parent=None, *args):
super(TableModel2, self).__init__()
#QtCore.QAbstractTableModel.__init__(self, parent, *args)
self.datatable = None
self.headerdata = None
self.dataFrame = None
self.model = QtGui.QStandardItemModel(self)
def update(self, dataIn):
print 'Updating Model'
self.datatable = dataIn
print 'Datatable : {0}'.format(self.datatable)
headers = dataIn.columns.values
header_items = [
str(field)
for field in headers
]
self.headerdata = header_items
print 'Headers'
print self.headerdata
for i in range(len(dataIn.index.values)):
for j in range(len(dataIn.columns.values)):
#self.datatable.setItem(i,j,QtGui.QTableWidgetItem(str(df.iget_value(i, j))))
self.model.setItem(i,j,QtGui.QStandardItem(str(dataIn.iget_value(i, j))))
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.datatable.index)
def columnCount(self, parent=QtCore.QModelIndex()):
return len(self.datatable.columns.values)
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return QtCore.QVariant()
elif role != QtCore.Qt.DisplayRole:
return QtCore.QVariant()
#return QtCore.QVariant(self.model.data(index))
return QtCore.QVariant(self.model.data(index))
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return QtCore.QVariant()
return QtCore.QVariant(self.headerdata[col])
def setData(self, index, value, role=QtCore.Qt.DisplayRole):
print "setData", index.row(), index.column(), value
def flags(self, index):
if (index.column() == 0):
return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled
else:
return QtCore.Qt.ItemIsEnabled
我正在尝试创建模型,然后将其添加到视图中,如下所示:
class Widget(QtGui.QWidget):
"""
A simple test widget to contain and own the model and table.
"""
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
l=QtGui.QVBoxLayout(self)
cdf = self.get_data_frame()
self._tm=TableModel(self)
self._tm.update(cdf)
self._tv=TableView(self)
self._tv.setModel(self._tm)
for row in range(0, self._tm.rowCount()):
self._tv.openPersistentEditor(self._tm.index(row, 0))
l.addWidget(self._tv)
def get_data_frame(self):
df = pd.DataFrame({'Name':['a','b','c','d'],
'First':[2.3,5.4,3.1,7.7], 'Last':[23.4,11.2,65.3,88.8], 'Class':[1,1,2,1], 'Valid':[True, True, True, False]})
return df
感谢您的关注!
注意:编辑2 我已将QStandardItemModel合并到TableModel2中。在@ mata的评论之后还删除了dataFrameToQtTable函数。这种情况越来越接近但仍无效。
答案 0 :(得分:13)
好的,我已经根据上述建议和Summerfield的Rapid GUI书籍提供了一些帮助。 QAbstractTableModel中不存在基础模型。只需要覆盖三个函数,数据可以以任何用户定义的格式存储,只要它在数据调用中返回即可。
一个非常简单的实现可能是:
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, parent=None, *args):
super(TableModel, self).__init__()
self.datatable = None
def update(self, dataIn):
print 'Updating Model'
self.datatable = dataIn
print 'Datatable : {0}'.format(self.datatable)
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.datatable.index)
def columnCount(self, parent=QtCore.QModelIndex()):
return len(self.datatable.columns.values)
def data(self, index, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
i = index.row()
j = index.column()
return '{0}'.format(self.datatable.iget_value(i, j))
else:
return QtCore.QVariant()
def flags(self, index):
return QtCore.Qt.ItemIsEnabled
这使您可以在Qt视图中查看任何可兼容的数据框。
我更新了here
上的要点如果您还需要这样做,这可以让您快速前进。
答案 1 :(得分:1)
这可能是你的问题:
def rowCount(self, parent=QtCore.QModelIndex()):
if type(self.datatable) == pd.DataFrame:
...
def columnCount(self, parent=QtCore.QModelIndex()):
if (self.datatable) == pd.DataFrame:
...
您将datatable
设置为QTableWidget
中的dataFrameToQtTable
,因此它不能是pd.DataFrame
,您的方法将始终返回0.
如果没有类型检查,您会立即发现问题。你真的想要默默地忽略你的类型不匹配的所有情况(如果它不遵循你期望的相同接口,最好让它引发错误)? Typechecks是in most cases unnecessary。
答案 2 :(得分:1)
Pandas 0.13提供了一个实验性功能:
PySide支持qtpandas DataFrameModel
和DataFrameWidget
请参阅https://github.com/pydata/pandas/blob/master/doc/source/faq.rst
您可以使用
添加此功能from pandas.sandbox.qtpandas import DataFrameModel, DataFrameWidget