可编辑的QTableView和Pandas无法正常工作 [英] Editable QTableView and Pandas do not work properly

查看:195
本文介绍了可编辑的QTableView和Pandas无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取一个完整的示例代码,以在获取可编辑的单元格视图时使用pandas和QTableView.

I am trying to get a self-contained piece of example code for using pandas and QTableView while getting editable cell views.

为此,我将继续进行较早的讨论: 可编辑QTableView中的熊猫df:删除复选框

For this I am following up to an earlier discussion: Pandas df in editable QTableView: remove check boxes

尽管其他讨论中的答案和建议的修改有助于摆脱复选框的影响,但是那里讨论的代码对我来说仍然不起作用(python 2.7).

While the answer and proposed modifications in that other discussion help to get rid of the checkboxes, the code discussed there is still not working for me (python 2.7).

当我使用下面的代码修改单元格时,该单元格中显示的内容是:...处的PtQt4.PtCore.QtVariant对象.

When I modify a cell using the code below, the content shown in the cell is: PtQt4.PtCore.QtVariant object at ...

我使用的软件包版本为:

The package versions I use are:

熊猫:0.20.2
Pyside 1.2.4
Qt版本:4.8.4
SIP版本:4.14.4 PyQt版本:4.10

Pandas: 0.20.2
Pyside 1.2.4
Qt version: 4.8.4
SIP version: 4.14.4 PyQt version: 4.10

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

    class PandasModelEditable(QtCore.QAbstractTableModel):
    def __init__(self, data, parent=None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self._data = data

    def rowCount(self, parent=None):
        return len(self._data.values)

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

    def data(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()])
        return None

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
            return None
        if 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()

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

    def setData(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)
                return True
        return False


if __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_())

推荐答案

直接的问题是由于将未转换的QVariant对象传递给基础数据库而引起的.最简单的解决方法是将其转换为python对象,如下所示:

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()

但是,这并不能真正解决代码中最根本的问题,即您正在使用Python和PyQt的旧版本. Qt不再正式支持Qt4,并且不久之后Python和Python2也会实现.严格来说,PyQt4已经过时的旧代码-因此,除非您有 确实 的充分理由(例如,向后兼容),否则您不应将其用于新项目.

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).

如果可以的话,我强烈建议您尽快将代码移植到Python3/PyQt5,因为这将在中长期内为您节省很多麻烦.但是,如果由于某种原因不能执行此操作,并且希望继续使用Python2/PyQt4,则可以通过在程序的开头添加以下内容来获得与PySide相同的行为:

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)
from PyQt4 import QtCore, QtGui

完成此操作后,PyQt会自动将所有QStringQVariant对象转换为普通的python数据类型,因此您将不需要进行任何显式转换(即,您可以删除所有这些unicode()toPyObject()调用您的代码).

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).

或者,您也可以将Python3与PyQt4一起使用,默认情况下其行为与PySide相同(因此不需要setapi东西).

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).

这篇关于可编辑的QTableView和Pandas无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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