Python PyQt5-在QTableWidget后面更新数据帧
如果用户在GUI中修改了某个特定元素,那么使用Qt方法更新数据帧时会遇到问题 例如,当我运行下面的代码时,我得到一个10×3的数据帧,其中显示了随机值。如果我试图将任何单元格更改为值400,我将双击,键入400,然后按enter键。当我打印数据帧时,该值仍然是旧值。我希望DataFrame单元格在用户更改值时更新 非常感谢Python PyQt5-在QTableWidget后面更新数据帧,python,pandas,pyqt,pyqt5,qtablewidget,Python,Pandas,Pyqt,Pyqt5,Qtablewidget,如果用户在GUI中修改了某个特定元素,那么使用Qt方法更新数据帧时会遇到问题 例如,当我运行下面的代码时,我得到一个10×3的数据帧,其中显示了随机值。如果我试图将任何单元格更改为值400,我将双击,键入400,然后按enter键。当我打印数据帧时,该值仍然是旧值。我希望DataFrame单元格在用户更改值时更新 非常感谢 import sys import numpy as np import pandas as pd from PyQt5.QtWidgets import * from Py
import sys
import numpy as np
import pandas as pd
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon, QColor
from PyQt5.QtCore import pyqtSlot, Qt, QTimer
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(700, 100, 350, 380)
self.createTable()
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.button = QPushButton('Print DataFrame', self)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.button.clicked.connect(self.print_my_df)
self.tableWidget.doubleClicked.connect(self.on_click_table)
self.show()
def createTable(self):
self.tableWidget = QTableWidget()
self.df_rows = 10
self.df_cols = 3
self.df = pd.DataFrame(np.random.randn(self.df_rows, self.df_cols))
self.tableWidget.setRowCount(self.df_rows)
self.tableWidget.setColumnCount(self.df_cols)
for i in range(self.df_rows):
for j in range(self.df_cols):
x = '{:.3f}'.format(self.df.iloc[i, j])
self.tableWidget.setItem(i, j, QTableWidgetItem(x))
@pyqtSlot()
def print_my_df(self):
print(self.df)
@pyqtSlot()
def on_click_table(self):
for currentQTableWidgetItem in self.tableWidget.selectedItems():
print((currentQTableWidgetItem.row(), currentQTableWidgetItem.column()))
self.print_my_df()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
QTableWidget
不知道DataFrame
的存在,因此它不会更新它。为此,我们必须更新它。我们使用给出行和列的cellChanged
信号,然后使用item()
方法返回给定列和行的QTableWidgetItem
,然后使用QTableWidgetItem
的text()
方法
放置在用户版本项中的数据可以是任何类型,例如文本,这将产生错误,因为DataFrame
仅接受数字值。我们必须提供一个输入来验证这一点,我们使用QDoubleValidator
放置QLineEdit
class FloatDelegate(QItemDelegate):
def __init__(self, parent=None):
QItemDelegate.__init__(self, parent=parent)
def createEditor(self, parent, option, index):
editor = QLineEdit(parent)
editor.setValidator(QDoubleValidator())
return editor
class TableWidget(QTableWidget):
def __init__(self, df, parent=None):
QTableWidget.__init__(self, parent)
self.df = df
nRows = len(self.df.index)
nColumns = len(self.df.columns)
self.setRowCount(nRows)
self.setColumnCount(nColumns)
self.setItemDelegate(FloatDelegate())
for i in range(self.rowCount()):
for j in range(self.columnCount()):
x = '{:.3f}'.format(self.df.iloc[i, j])
self.setItem(i, j, QTableWidgetItem(x))
self.cellChanged.connect(self.onCellChanged)
@pyqtSlot(int, int)
def onCellChanged(self, row, column):
text = self.item(row, column).text()
number = float(text)
self.df.set_value(row, column, number)
例如:
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(700, 100, 350, 380)
df_rows = 10
df_cols = 3
df = pd.DataFrame(np.random.randn(df_rows, df_cols))
self.tableWidget = TableWidget(df, self)
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.button = QPushButton('Print DataFrame', self)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.button.clicked.connect(self.print_my_df)
@pyqtSlot()
def print_my_df(self):
print(self.tableWidget.df)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
QTableWidget
不知道DataFrame
的存在,因此它不会更新它。为此,我们必须更新它。我们使用给出行和列的cellChanged
信号,然后使用item()
方法返回给定列和行的QTableWidgetItem
,然后使用QTableWidgetItem
的text()
方法
放置在用户版本项中的数据可以是任何类型,例如文本,这将产生错误,因为DataFrame
仅接受数字值。我们必须提供一个输入来验证这一点,我们使用QDoubleValidator
放置QLineEdit
class FloatDelegate(QItemDelegate):
def __init__(self, parent=None):
QItemDelegate.__init__(self, parent=parent)
def createEditor(self, parent, option, index):
editor = QLineEdit(parent)
editor.setValidator(QDoubleValidator())
return editor
class TableWidget(QTableWidget):
def __init__(self, df, parent=None):
QTableWidget.__init__(self, parent)
self.df = df
nRows = len(self.df.index)
nColumns = len(self.df.columns)
self.setRowCount(nRows)
self.setColumnCount(nColumns)
self.setItemDelegate(FloatDelegate())
for i in range(self.rowCount()):
for j in range(self.columnCount()):
x = '{:.3f}'.format(self.df.iloc[i, j])
self.setItem(i, j, QTableWidgetItem(x))
self.cellChanged.connect(self.onCellChanged)
@pyqtSlot(int, int)
def onCellChanged(self, row, column):
text = self.item(row, column).text()
number = float(text)
self.df.set_value(row, column, number)
例如:
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(700, 100, 350, 380)
df_rows = 10
df_cols = 3
df = pd.DataFrame(np.random.randn(df_rows, df_cols))
self.tableWidget = TableWidget(df, self)
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.button = QPushButton('Print DataFrame', self)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.button.clicked.connect(self.print_my_df)
@pyqtSlot()
def print_my_df(self):
print(self.tableWidget.df)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
谢谢,
cellChanged
真的把这个问题搞砸了!:)太好了,但是当我的数据帧索引不是0,1,2,3…,它仍然把0,1,2,3。。。作为索引,如何使其成为实际的数据帧索引?谢谢,cellChanged
真的把这个问题彻底解决了!:)太好了,但是当我的数据帧索引不是0,1,2,3…,它仍然把0,1,2,3。。。作为索引,如何使其成为实际的数据帧索引?