2017-12-29 43 views
1

QTableView内のセル(ヘッダを除く)を変更したいと思います。ここでは、以下のいずれかの変更を許可しない私の元のコードです:QTableView PYQT5のセルを変更する

import sys 
import csv 
from datetime import datetime, timedelta 
import calendar 
from PyQt5.QtWidgets import * 
from PyQt5.QtCore import * 
from PyQt5.QtGui import * 
import sqlite3 
from pandas import DataFrame 

class TBWindow(QMainWindow): 
    def __init__(self, parent=None): 
     super(TBWindow, self).__init__(parent) 

     sql = "select * from stock" 
     args = [] 

     conn = sqlite3.connect('DataBase.db') 
     c = conn.cursor() 
     c.execute(sql,args) 
     data = c.fetchall() 
     names = list(map(lambda x: x[0], c.description)) 
     c.close() 
     conn.close() 
     data = DataFrame(data, columns = names) 

     MenuBar = self.menuBar() 
     saveFile = QAction("&Save File", self) 
     saveFile.setShortcut("Ctrl+S") 
     saveFile.setStatusTip('Save File') 
     saveFile.triggered.connect(self.file_save) 
     MenuBar.addAction(saveFile) 

     self.setWindowTitle('Aplikace Princezna Pampeliska') 
     self.centralwidget = QWidget(self) 
     self.lineEdit  = QLineEdit(self.centralwidget) 
     self.view   = QTableView(self.centralwidget) 
     self.comboBox  = QComboBox(self.centralwidget) 
     self.label   = QLabel(self.centralwidget) 

     self.gridLayout = QGridLayout(self.centralwidget) 
     self.gridLayout.addWidget(self.lineEdit, 0, 1, 1, 1) 
     self.gridLayout.addWidget(self.view, 1, 0, 1, 3) 
     self.gridLayout.addWidget(self.comboBox, 0, 2, 1, 1) 
     self.gridLayout.addWidget(self.label, 0, 0, 1, 1) 

     self.setCentralWidget(self.centralwidget) 
     self.label.setText("Filter") 

     self.model = PandasModel(data) 

     self.proxy = QSortFilterProxyModel(self) 
     self.proxy.setSourceModel(self.model) 

     self.view.setModel(self.proxy) 

     for column in range(self.view.horizontalHeader().count()): 
      self.view.resizeColumnToContents(column) 

     for i in (0,1,3): 
      self.view.horizontalHeader().setSectionResizeMode(i, QHeaderView.Stretch)    

     self.comboBox.addItems(list(data.columns.values)) 
     self.lineEdit.textChanged.connect(self.on_lineEdit_textChanged) 
     self.comboBox.currentIndexChanged.connect(self.on_comboBox_currentIndexChanged) 

     self.horizontalHeader = self.view.horizontalHeader() 

    def file_save(self): 
     newModel = self.view.model() 
     data = [] 
     for row in range(newModel.rowCount()): 
      rowRes = [] 
      for column in range(newModel.columnCount()): 
       index = newModel.index(row, column) 
       item = newModel.data(index) 
       if item != '': 
        rowRes.append(item) 
      data.append(rowRes) 
     dataFrame = DataFrame(data) 

     options = QFileDialog.Options() 
     options |= QFileDialog.DontUseNativeDialog 
     fileName, fEnd = QFileDialog.getSaveFileName(self, "Save File", "", ".csv") 
     if fileName: 
      address = fileName+fEnd 
      dataFrame.to_csv(address, index=False, header=False) 

    @pyqtSlot(str) 
    def on_lineEdit_textChanged(self, text): 
     search = QRegExp(text, Qt.CaseInsensitive, QRegExp.RegExp) 
     self.proxy.setFilterRegExp(search) 

    @pyqtSlot(int) 
    def on_comboBox_currentIndexChanged(self, index): 
     self.proxy.setFilterKeyColumn(index) 

class PandasModel(QAbstractTableModel): 

    def __init__(self, data, parent=None): 
     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 data(self, index, role=Qt.DisplayRole): 
     if index.isValid(): 
      if role == Qt.DisplayRole: 
       return str(self._data.iloc[index.row(), index.column()]) 
     return None 

    def headerData(self, col, orientation, role): 
     if orientation == Qt.Horizontal and role == Qt.DisplayRole: 
      return self._data.columns[col] 
     return None 

if __name__ == '__main__': 

    app = QApplication(sys.argv) 
    main = TBWindow() 
    main.showMaximized() 
    sys.exit(app.exec_()) 

私はQTableView内のセルの変更に関するいくつかの記事を読んで、もう1つはモデルではないビューを変更する必要があることを見出しました。したがって、このコードのビットの付加は、細胞が編集可能になります:

def flags(self, index): 
    flags = super(self.__class__,self).flags(index) 
    flags |= Qt.ItemIsEditable 
    flags |= Qt.ItemIsSelectable 
    flags |= Qt.ItemIsEnabled 
    flags |= Qt.ItemIsDragEnabled 
    flags |= Qt.ItemIsDropEnabled 
    return flags 

ただし、変更は、彼らは私が他の場所でクリックした直後に消え、保持されません。このようにして関数setData()を追加しようとしました。

def setData(self, index, value, role=Qt.EditRole): 
    row = index.row() 
    col = index.column() 
    self._data[row][name] = value 
    self.emit(SIGNAL('dataChanged()')) 
    return True 

プログラムはいくつかのキーエラーで終了します。どのような変更をすべきですか?ありがとう!

答えて

2

あなたのコードでは、2個のエラーがあります:

  • 悪いプログラミング手法によって引き起こされる最初:あなたが他の変数、関数やクラスで使用する名前を持つ変数を呼び出すべきではありません。あなたのケースのフラグにはメソッドの名前であり、したがって、あなたは変数の名前でそれを使用しないでください:あなたはありませんので、

def flags(self, index): 
    fl = super(self.__class__,self).flags(index) 
    fl |= Qt.ItemIsEditable 
    fl |= Qt.ItemIsSelectable 
    fl |= Qt.ItemIsEnabled 
    fl |= Qt.ItemIsDragEnabled 
    fl |= Qt.ItemIsDropEnabled 
    return fl 

  • 2番目のエラーが発生します適切な方法を使用してパンダのデータにアクセスし、割り当てます。これは、ilocメソッドを使用して行う必要があります。もう一つの問題は、あなたが変更を通知するPyQt4のための有効な方法を使用している、あなたはdocsで見ることができるようQt5で新しいフィールドを追加する新しい構文プラスdataChanged信号を使用しなければならないということです:

def setData(self, index, value, role=Qt.EditRole): 
    if index.isValid(): 
     row = index.row() 
     col = index.column() 
     self._data.iloc[row][col] = float(value) 
     self.dataChanged.emit(index, index, (Qt.DisplayRole,)) 
     return True 
    return False 

プラス:あなたが質問How to display a Pandas data frame with PyQt5

+0

に見ることができるように私も以前にパンダを使用してモデルを作成するクラスを実装している

あなたのお勧め/助けをありがとう。私はfloat()を削除して動作します。 – New2Python

関連する問題