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