Python PyQt5-在QTableWidget后面更新数据帧

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

如果用户在GUI中修改了某个特定元素,那么使用Qt方法更新数据帧时会遇到问题

例如,当我运行下面的代码时,我得到一个10×3的数据帧,其中显示了随机值。如果我试图将任何单元格更改为值400,我将双击,键入400,然后按enter键。当我打印数据帧时,该值仍然是旧值。我希望DataFrame单元格在用户更改值时更新

非常感谢

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。。。作为索引,如何使其成为实际的数据帧索引?