PyQt5 - 在 QTableWidget 后面更新 DataFrame
PyQt5 - Updating DataFrame behind QTableWidget
如果用户在 GUI 中修改了特定元素,我在使用 Qt 方法更新 DataFrame 时遇到问题。
例如,当我 运行 以下代码时,我得到一个 10 x 3 的 DataFrame,其中显示了随机值。如果我尝试将任何单元格更改为值 400,我双击,键入 400,然后按回车键。当我打印 DataFrame 时,该值仍然是旧值。我希望 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()
方法 returns QTableWidgetItem
给定列和行, 那么我们使用QTableWidgetItem
.
的text()
方法
放置在用户版本项目中的数据可以是任何类型,例如文本,这会产生错误,因为 DataFrame
只接受数值,为此我们必须提供输入为了验证这一点,我们放置了一个 QLineEdit
和一个 QDoubleValidator
.
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_())
如果用户在 GUI 中修改了特定元素,我在使用 Qt 方法更新 DataFrame 时遇到问题。
例如,当我 运行 以下代码时,我得到一个 10 x 3 的 DataFrame,其中显示了随机值。如果我尝试将任何单元格更改为值 400,我双击,键入 400,然后按回车键。当我打印 DataFrame 时,该值仍然是旧值。我希望 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()
方法 returns QTableWidgetItem
给定列和行, 那么我们使用QTableWidgetItem
.
text()
方法
放置在用户版本项目中的数据可以是任何类型,例如文本,这会产生错误,因为 DataFrame
只接受数值,为此我们必须提供输入为了验证这一点,我们放置了一个 QLineEdit
和一个 QDoubleValidator
.
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_())