18

PyQt テーブルに pandas データ フレームを表示したいと思います。私はこれである程度の進歩を遂げましたが、Table Model クラスを正しく派生させることができませんでした。これについての助けは大歓迎です。

** 完全なサンプル コードはこちら**

有効な QtCore.QAbstractTableModel 派生クラスを生成するのに苦労しています。QItemDelegates に関する以前の質問に続いて、実際のデータを挿入するために Pandas DataFrame からテーブル モデルを生成しようとしています。ここにサンプル コードがありますが、TableModel を Widget クラス (ln 152) の TableModel2 に置き換えると、テーブルを表示できません。

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 関数を削除しました。これは少し近づいていますが、まだ機能していません。

4

4 に答える 4

17

上記の提案と、Summerfield による Rapid GUI book の助けを借りて、これを理解しました。QAbstractTableModel に存在する基礎となるモデルはありません。オーバーライドする必要があるのは 3 つの関数だけであり、データ呼び出しで返される限り、データは任意のユーザー定義形式で格納できます。

非常に単純な実装は次のようになります。

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 ビューで表示できます。

ここの要点を更新しました

これを行う必要がある場合は、これですぐに作業を進めることができます。

于 2013-07-17T14:37:27.170 に答える
2

これはおそらくあなたの問題です:

def rowCount(self, parent=QtCore.QModelIndex()):
    if type(self.datatable) == pd.DataFrame:
    ...


def columnCount(self, parent=QtCore.QModelIndex()):
    if (self.datatable) == pd.DataFrame:
    ...

あなたはあなたdatatableQTableWidgetindataFrameToQtTableに設定するのでpd.DataFrame、あなたのメソッドは常に 0 を返します。

型チェックがなければ、すぐに問題を発見できたでしょう。型が一致しないすべてのケースを黙って無視しますか (期待しているのと同じインターフェイスに従っていない場合はエラーを発生させます) ほとんどの場合、型チェックは不要です。

于 2013-07-17T11:15:07.247 に答える
1

Pandas 0.13 は実験的な機能として以下を提供します。

qtpandasDataFrameModelおよびDataFrameWidget

https://github.com/pydata/pandas/blob/master/doc/source/faq.rstを参照してください

を使用してこの機能を追加できます

from pandas.sandbox.qtpandas import DataFrameModel, DataFrameWidget
于 2014-03-04T08:06:52.707 に答える