在qTableView Python PyQt5中编辑后更新数据帧

在qTableView Python PyQt5中编辑后更新数据帧,python,pyqt5,qtableview,qabstracttablemodel,Python,Pyqt5,Qtableview,Qabstracttablemodel,你好 我正在尝试将数据帧加载到PyQt5 QTableView中,以允许使用ComboBox编辑最后一列。编辑完成后,打印数据框,以便我可以进一步编辑它。单击“打印数据”时,无法打印更新的QTableView模型。代码如下所示 import sys from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit, QTextEdit, QGridLayout, QApplication) import pandas as pd import num

你好

我正在尝试将数据帧加载到PyQt5 QTableView中,以允许使用ComboBox编辑最后一列。编辑完成后,打印数据框,以便我可以进一步编辑它。单击“打印数据”时,无法打印更新的QTableView模型。代码如下所示

import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit, QTextEdit, QGridLayout, QApplication)
import pandas as pd
import numpy as np
import PyQt5 
from PyQt5.QtWidgets import QVBoxLayout, QPushButton, QGroupBox, QHBoxLayout, QMainWindow, QApplication, QLineEdit, QFileDialog,  QTableWidget,QTableWidgetItem, QTableView, QStyledItemDelegate
from PyQt5 import QtCore, QtGui, QtWidgets   
import os
from PyQt5.QtWidgets import (QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QApplication)
from PyQt5.QtGui import QIcon
import re

def dataframe():
    lst = [['tom', 'reacher', 'True'], ['krish', 'pete', 'True'], 
           ['nick', 'wilson', 'True'], ['juli', 'williams', 'True']] 
    df = pd.DataFrame(lst, columns =['FName', 'LName', 'Student?'], dtype = float) 
    return df

class Delegate(QtWidgets.QItemDelegate):
    def __init__(self, owner, choices):
        super().__init__(owner)
        self.items = choices

    def createEditor(self, parent, option, index):
        self.editor = QtWidgets.QComboBox(parent)
        self.editor.currentIndexChanged.connect(self.commit_editor)
        self.editor.addItems(self.items)
        return self.editor    

    def paint(self, painter, option, index):
        value = index.data(QtCore.Qt.DisplayRole)
        style = QtWidgets.QApplication.style()
        opt = QtWidgets.QStyleOptionComboBox()
        opt.text = str(value)
        opt.rect = option.rect
        style.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, opt, painter)
        QtWidgets.QItemDelegate.paint(self, painter, option, index)

    def commit_editor(self):      ####test
        editor = self.sender()
        self.commitData.emit(editor)


    def setEditorData(self, editor, index):
        value = index.data(QtCore.Qt.DisplayRole)
        num = self.items.index(value)
        editor.setCurrentIndex(num)

    def setModelData(self, editor, model, index):
        value = editor.currentText()
        model.setData(index, value, QtCore.Qt.EditRole)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)


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

    def rowCount(self, parent=None):
        return self._data.shape[0]

    def columnCount(self, parent=None):
        return self._data.shape[1]

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

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if index.isValid():
            if role == QtCore.Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, col, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return self._data.columns[col]
        return None

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        self._data[index.row()][index.column()] = value
        self.dataChanged.emit(index, index, (QtCore.Qt.DisplayRole, ))
        return True 

class MyWindow(QWidget):

    def __init__(self):
        super().__init__()
        self.setGeometry(300, 200 ,600, 400)
        self.setWindowTitle('Test')
        self.initUI()


    def show_data(self):
        choices = ['True', 'False']
        self.model = PandasModel(dataframe())
        self.table_data.setModel(self.model)                            
        self.table_data.setItemDelegateForColumn(2, Delegate(self,choices))
        ##make combo boxes editable with a single-click:
        for row in range(5):  
            self.table_data.openPersistentEditor(self.model.index(row, 2))

    def print_data(self):
        print(self.table_data.model()._data)

    def initUI(self):

        welcom = QLabel('Welcome to my app!')

        self.btn_print_data = QPushButton('print data')
        self.btn_print_data.clicked.connect(self.print_data)  ##test

        self.btn_show_table = QPushButton('show data')
        self.btn_show_table.clicked.connect(self.show_data)

        self.table_data = QTableView()
        #self.table_result = QTableView()

        hbox1 = QHBoxLayout()
        hbox1.addWidget(welcom)


        vbox2 = QVBoxLayout()
        vbox2.addWidget(self.btn_show_table)
        vbox2.addWidget(self.btn_print_data) ####test

        vbox3 = QVBoxLayout()
        vbox3.addWidget(self.table_data)
        #vbox3.addWidget(self.table_result)

        hbox2 = QHBoxLayout()
        hbox2.addLayout(vbox2)
        hbox2.addLayout(vbox3)

        vbox1 = QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.addLayout(hbox2)

        self.setLayout(vbox1)
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyWindow()
    sys.exit(app.exec_())


首先,我无法运行您的代码,因此我更改了:

def setData(self, index, value, role=QtCore.Qt.EditRole):
    self._data[index.row()][index.column()] = value

然后我意识到,每次单击“显示数据”按钮时,都会再次加载原始数据帧,因此它会删除所有更改

    def show_data(self):
        ...
        self.model = PandasModel(dataframe())
所以我在init中添加了“self.df=dataframe()

然后更改了show_数据

    def show_data(self):
        ...
        self.model = PandasModel(self.df)
我认为这解决了问题,我希望这将对您和我都有帮助,我来这里是为了在PyQt5中搜索这种可编辑Pandas表的实现

    def __init__(self):
        ....
        self.df = dataframe()
    def show_data(self):
        ...
        self.model = PandasModel(self.df)