PyQt - 实现 QAbstractTableModel 以在 QTableView 中显示 [英] PyQt - Implement a QAbstractTableModel for display in QTableView

查看:44
本文介绍了PyQt - 实现 QAbstractTableModel 以在 QTableView 中显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 PyQt 表中显示一个 Pandas 数据框.我在这方面取得了一些进展,但无法正确派生 Table Model 类.对此的任何帮助将不胜感激.

I would like to display a pandas data frame in a PyQt table. I have made some progress with this, but have not been able to correctly derive the Table Model class. Any help with this would be much appreciated.

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

** Note full example code here **

我正在努力生成有效的 QtCore.QAbstractTableModel 派生类.继上一个关于 QItemDelegates 的问题之后,我试图从 Pandas DataFrame 生成表模型以插入真实数据.我有工作示例代码这里,但是如果我在 Widget 类 (ln 152) 中用 TableModel2 替换我的 TableModel,我无法得到要显示的表格.

I am struggling to generate a valid QtCore.QAbstractTableModel derived class. Following on from a previous question about QItemDelegates I am trying to generate a table model from a Pandas DataFrame to insert real data. I have working example code here, but if I replace my TableModel with TableModel2 in the Widget class (ln 152) I cannot get the table to display.

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 

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

I am attempting to create the model and then add it to the view, like this:

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 函数.这越来越近了,但仍然无法正常工作.

Note : Edit 2 I have incorporated the QStandardItemModel into TableModel2. Also deleted the dataFrameToQtTable function after @mata's comment. This is getting a bit closer but still not working.

推荐答案

好的,我已经根据上述建议和 Summerfield 的 Rapid GUI 一书中的一些帮助解决了这个问题.QAbstractTableModel 中不存在底层模型.只需要重写三个函数,数据可以以任何用户定义的格式存储,只要在数据调用中返回即可.

Ok I have figured this one out with the above suggestion and some help from the Rapid GUI book by Summerfield. There is no underlying model that exists in the QAbstractTableModel. Only three functions need be overridden, and the data may be stored in any user defined format, as long as it is returned in the data call.

一个非常简单的实现可能是:

A very simple implementation could be:

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 视图中查看任何兼容的数据框.

This enables you to view any compatable data frame in a Qt view.

我在这里

如果您也需要这样做,这应该能让您快速上手.

This should get you going quickly if you also need to do this.

这篇关于PyQt - 实现 QAbstractTableModel 以在 QTableView 中显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆