Skip to content Skip to sidebar Skip to footer

Editable Qtableview And Pandas Do Not Work Properly

I am trying to get a self-contained piece of example code for using pandas and QTableView while getting editable cell views. For this I am following up to an earlier discussion: Pa

Solution 1:

The immediate problem is caused by passing an unconverted QVariant object to the underlying database. The simplest fix is convert it to a python object, like this:

self._data.iloc[index.row(), index.column()] = value.toPyObject()

However, this doesn't really deal with the most fundamental problem with the code, which is that you are using such old versions of Python and PyQt. Qt does not officially support Qt4 any more, and it won't be long before the same is true for Python and Python2. Strictly speaking, PyQt4 is already obsolete legacy code - so you shouldn't be using it for new projects unless you have a really good reason for doing that (e.g. backwards compatibilty).

If you can, I would strongly recommend that you port your code to Python3/PyQt5 as soon as possible, as it will save you a lot of hassle in the medium to long term. However, if you cannot do this for some reason, and you want to continue using Python2/PyQt4, you can get the same behaviour as PySide by adding the following to the beginning of your program:

import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
fromPyQt4importQtCore, QtGui

After doing this, PyQt will automatically convert all QString and QVariant objects to ordinary python data types, so you will never need to do any explicit conversions (i.e. you can remove all those unicode() and toPyObject() calls in your code).

Alternatively, you could also use Python3 with PyQt4, which has the same behaviour as PySide by default (so the setapi stuff would not be needed).

Solution 2:

It seems to work when I switch to PySide instead of PyQt4:

import sys
from PySide import QtCore, QtGui
import pandas as pd
Qt = QtCore.Qt

    classPandasModelEditable(QtCore.QAbstractTableModel):
    def__init__(self, data, parent=None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self._data = data

    defrowCount(self, parent=None):
        returnlen(self._data.values)

    defcolumnCount(self, parent=None):
        return self._data.columns.size

    defdata(self, index, role=QtCore.Qt.DisplayRole):
        if index.isValid():
            if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
                return unicode(self._data.iloc[index.row(), index.column()])
        returnNonedefheaderData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
            returnNoneif orientation == QtCore.Qt.Horizontal:
            try:
                return'%s' % unicode(self._data.columns.tolist()[section])
            except (IndexError,):
                return unicode()
        elif orientation == QtCore.Qt.Vertical:
            try:
                return'%s' % unicode(self._data.index.tolist()[section])
            except (IndexError,):
                return unicode()

    defflags(self, index):
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | \
               QtCore.Qt.ItemIsEditable

    defsetData(self, index, value, role=QtCore.Qt.EditRole):
        if index.isValid():
            self._data.iloc[index.row(), index.column()] = value
            if self.data(index, QtCore.Qt.DisplayRole) == value:
                self.dataChanged.emit(index, index)
                returnTruereturnFalseif __name__ == '__main__':
    application = QtGui.QApplication(sys.argv)
    view = QtGui.QTableView()
    df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=['a', 'b', 'c'], index=['x', 'y'])

    model = PandasModelEditable(df)
    view.setModel(model)

    view.show()
    sys.exit(application.exec_())

Post a Comment for "Editable Qtableview And Pandas Do Not Work Properly"