python - संपादनयोग्य QTableView और Pandas ठीक से काम नहीं करते




model pyqt4 (2)

संपादन योग्य दृश्यों को प्राप्त करते समय मैं पंडों और क्यूटेबल दृश्य का उपयोग करने के लिए उदाहरण के कोड का आत्म-निहित टुकड़ा प्राप्त करने की कोशिश कर रहा हूं।

इसके लिए मैं पहले की चर्चा का पालन कर रहा हूं: संपादन योग्य QTableView में Pandas DF: चेक बॉक्स को हटा दें

जबकि अन्य चर्चा में जवाब और प्रस्तावित संशोधनों से चेकबॉक्स को छुटकारा पाने में सहायता मिलती है, वहां पर चर्चा की गई कोड मेरे लिए अभी भी काम नहीं कर रहा है (अजगर 2.7)।

जब मैं नीचे कोड का उपयोग कर एक कक्ष को संशोधित करता हूं, तो सेल में दिखाया गया सामग्री है: PtQt4.PtCore.QtVariant ऑब्जेक्ट ...

मेरे द्वारा उपयोग किए जाने वाले पैकेज संस्करण हैं:

पांडा: 0.20.2
पाइसाइड 1.2.4
क्यूटी संस्करण: 4.8.4
एसआईपी संस्करण: 4.14.4 पीएईटीटी संस्करण: 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_())

ऐसा लगता है कि जब मैं PyQt4 के बजाय PySide पर स्विच करता हूं:

import sys
from PySide 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 ऑब्जेक्ट गुजरने के कारण होती है। सरलतम तय यह एक अजगर ऑब्जेक्ट में बदलता है, जैसे:

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

हालांकि, यह वास्तव में कोड के साथ सबसे मौलिक समस्या से निपटने के लिए नहीं है, जो कि आप पायथन और पीएएटीटी के पुराने संस्करणों का उपयोग कर रहे हैं। Qt आधिकारिक तौर पर किसी भी अधिक Qt4 का समर्थन नहीं करता है, और यह पायथन और पायथन 2 के लिए सही होने से पहले लंबा नहीं होगा। कड़ाई से बोलते हुए, PyQt4 पहले से ही अप्रचलित विरासत कोड है - इसलिए आपको इसे नई परियोजनाओं के लिए उपयोग नहीं करना चाहिए, जब तक आपके पास ऐसा करने का एक बहुत अच्छा कारण नहीं है (जैसे पीछे की ओर compatibilty)।

यदि आप कर सकते हैं, तो मैं दृढ़ता से अनुशंसा करता हूं कि आप जितनी जल्दी हो सके Python3 / PyQt5 को अपना कोड बंद कर दें, क्योंकि इससे आपको लंबे समय तक माध्यम से बहुत परेशानी की बचत होगी। हालांकि, यदि आप किसी कारण के लिए ऐसा नहीं कर सकते हैं, और आप Python2 / PyQt4 का उपयोग जारी रखना चाहते हैं, तो आप अपने कार्यक्रम की शुरुआत में निम्नलिखित को जोड़कर, PySide के समान व्यवहार प्राप्त कर सकते हैं:

import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
from PyQt4 import QtCore, QtGui

ऐसा करने के बाद, PyQt स्वचालित रूप से सभी QVariant और QVariant वस्तुओं को साधारण अजगर डेटा प्रकारों में परिवर्तित कर देगा, ताकि आपको किसी भी स्पष्ट रूपांतरण की आवश्यकता नहीं होगी (यानी आप अपने कोड में उन सभी unicode() और toPyObject() कॉल को निकाल सकते हैं)।

वैकल्पिक रूप से, आप Py Python3 को PyQt4 के साथ भी इस्तेमाल कर सकते हैं, जिसका डिफ़ॉल्ट रूप से PySide के समान व्यवहार है (इसलिए setapi सामान की आवश्यकता नहीं होगी)।







qtableview