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

查看:34
本文介绍了可编辑的 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 中的 Pandas 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 object at ...

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.4PyQt 版本: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天全站免登陆