2017-12-29 11 views
1

Ich möchte jede Zelle (außer Header) innerhalb gegebener QTableView ändern. Hier unten ist mein ursprünglicher Code, der nicht für alle Änderungen erlaubt:Ändern von Zellen in 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_()) 

ich einige Artikel gelesen habe, um Zellen innerhalb QTableView Modifizierung und fand heraus, dass man das Modell zu ändern, braucht nicht die Aussicht. Daraus ergibt sich die Zugabe dieses Stück Code macht die Zellen editierbar:

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 

jedoch nicht die Änderungen bestehen bleiben, verschwinden sie gleich nachdem ich an anderer Stelle klicken. Ich habe versucht, Funktion setData() auf diese Weise ohne Erfolg hinzuzufügen:

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 

Das Programm wird mit einigen Schlüsselfehler beendet. Irgendwelche Vorschläge, was geändert werden sollte? Vielen Dank!

Antwort

2

Ihr Code hat zwei Fehler:

  • die erste durch eine schlechte Programmierpraxis verursacht: Sie sollten die Variablen mit Namen nicht nennen, die Sie mit anderen Variablen, Funktionen oder Klassen verwendet. In Ihrem Fall Fahnen ist der Name der Methode und deshalb sollten Sie es nicht im Namen der Variablen verwenden:

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 

  • Der zweite Fehler wird dadurch verursacht, dass Sie nicht sind Mit der richtigen Methode für den Zugriff und die Zuweisung der Daten in Pandas muss dies über die iloc-Methode geschehen. Ein weiteres Problem ist, dass Sie eine gültige Methode verwenden für PyQt4 die Änderungen in Kenntnis zu setzen, müssen Sie die neue Syntax verwenden und das datachanged Signal, um neue Felder in QT5 hinzufügen, wie Sie in den docs sehen:

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 

plus-:

ich habe früher auch eine Klasse implementiert, die ein Modell Pandas mit erzeugt, wie Sie in der Frage How to display a Pandas data frame with PyQt5

+0

sehen Danke für deine Empfehlungen/Hilfe. Ich habe float() entfernt und es funktioniert. – New2Python

Verwandte Themen