2017-10-30 24 views
0

GUIでユーザーが変更した特定の要素がある場合、QtメソッドでDataFrameを更新する際に問題が発生します。PyQt5 - QTableWidgetの背後にあるDataFrameを更新する

たとえば、次のコードを実行すると、ランダム値が表示された10x3 DataFrameが表示されます。任意のセルを値400に変更しようとすると、ダブルクリックし、400と入力してEnterキーを押します。私が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_()) 

答えて

1

QTableWidgetDataFrameの存在を知らないので、それはそれを更新していません。これを更新する必要があります。cellChanged信号を使用して行と列を指定し、次にitem()メソッドを使用して、QTableWidgetItemの列と行を返し、次にtext()メソッドをQTableWidgetItemとします。

ユーザーのエディションのアイテムに配置されるデータは、テキストなどの任意のタイプにすることができます。DataFrameは数字のみを受け入れるため、エラーが発生します。これを検証する入力が必要ですQLineEditQDoubleValidatorと置きます。

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_()) 
+0

は 'cellChanged'が本当に質問広いオープンを吹いた、ありがとうございます! :) –

関連する問題