PyQt - 实现QAbstractTableModel以在QTableView中显示

dre*_*iya 16 python qt qt4 pyqt

我想在PyQt表中显示一个pandas数据帧.我已经取得了一些进展,但是无法正确派生Table Model类.任何有关这方面的帮助将非常感激.

**注意这里的完整示例代码**

我正在努力生成一个有效的QtCore.QAbstractTableModel派生类.继上一个关于QItemDelegates的问题后,我试图从Pandas DataFrame生成一个表模型来插入实际数据.我在这里有一些示例代码,但如果我在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 
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建模型,然后将其添加到视图中,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

感谢您的关注!

注意:编辑2我已将QStandardItemModel合并到TableModel2中.在@ mata的评论之后还删除了dataFrameToQtTable函数.这有点接近但仍然无法正常工作.

dre*_*iya 15

好的,我已经根据上述建议和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
Run Code Online (Sandbox Code Playgroud)

这使您可以在Qt视图中查看任何可兼容的数据框.

我在这里更新了Gist

如果您还需要这样做,这应该可以让您快速前进.