首页 > 解决方案 > QT 表格单元格编辑错误:只有整数、切片 (`:`)、省略号 (`...`)、numpy.newaxis (`None`)

问题描述

使用 QT Python。在 QTableView 中显示从 csv 文件中加载的数据框。然后我编辑单元格,我得到错误。示例更改:双击后从 40 到 45 的值。

在此处输入图像描述

Traceback (most recent call last):
  File "C:/Users/villa/PycharmProjects/ForecastAPP/Forecastapp_02.py", line 96, in setData
    self._df.values[row][col] = value
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

在调试错误中

    def setData(self, index, value, role):
        row = self._df.index[index.row()]
        col = self._df.columns[index.column()]
        print(row)
        print(col)
        print(value)
        self._df.values[row][col] = value
        self.dataChanged.emit(index, index)
        return True

全班

class PandasModel_1(QAbstractTableModel):
    def __init__(self, df = pd.DataFrame(), parent=None):
        QAbstractTableModel.__init__(self, parent=None)
        self._df = df
        self.setChanged = False
        self.dataChanged.connect(self.setModified)

    def setModified(self):
        self.setChanged = True
        print(self.setChanged)

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            try:
                return self._df.columns.tolist()[section]
            except (IndexError, ):
                return QVariant()
        elif orientation == Qt.Vertical:
            try:
                return self._df.index.tolist()[section]
            except (IndexError, ):
                return QVariant()

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if (role == Qt.EditRole):
                return self._df.values[index.row()][index.column()]
            elif (role == Qt.DisplayRole):
                return self._df.values[index.row()][index.column()]
        return None

    def setData(self, index, value, role):
        row = self._df.index[index.row()]
        col = self._df.columns[index.column()]
        print(row)
        print(col)
        print(value)
        self._df.values[row][col] = value
        self.dataChanged.emit(index, index)
        return True

    def rowCount(self, parent=QModelIndex()):
        return len(self._df.index)

    def columnCount(self, parent=QModelIndex()):
        return len(self._df.columns)

    def sort(self, column, order):
        colname = self._df.columns.tolist()[column]
        self.layoutAboutToBeChanged.emit()
        self._df.sort_values(colname, ascending= order == Qt.AscendingOrder, inplace=True)
        self._df.reset_index(inplace=True, drop=True)
        self.layoutChanged.emit()

叫来

    def loadFile(self):
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open File", "", "CSV Files (*.csv)");
        self.pathLE1.setText(fileName)
        df = pd.read_csv(fileName)
        model = PandasModel_1(df)
        print(model)
        self.history1_data.setModel(model)
        self.history1_data.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.history1_data.setSelectionBehavior(self.history1_data.SelectRows)
        self.history1_data.setSelectionMode(self.history1_data.SingleSelection)

完整的程序

"""
@author: Pino Villa, app to manage ARIMA forecast . Version 2 load data into table and matplotplot
"""
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QApplication
from PyQt5.QtGui import QDoubleValidator
from PyQt5.QtCore import QAbstractTableModel, Qt
import matplotlib.pyplot as plt
from PyQt5.QtWidgets import QFileDialog
from matplotlib.backends.backend_qt5agg import (
    NavigationToolbar2QT as NavigationToolbar)
import pandas as pd
from PandasModel import PandasModel
from PandasModel_panda import PandasModel_panda
from tablemodel_editable import PandasModelx
from cnt_init_values import CntInitialValues
import sys, os
import warnings
import itertools
import numpy as np
import matplotlib.pyplot as plt
warnings.filterwarnings("ignore")
#plt.style.use('fivethirtyeight')
import pandas as pd
import statsmodels.api as sm
import matplotlib
import sys
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QDir, QItemSelectionModel, QAbstractTableModel, QModelIndex, QVariant, QSize, QSettings
from PyQt5.QtWidgets import (QMainWindow, QTableView, QApplication, QToolBar, QLineEdit, QComboBox, QDialog,
                             QAction, QMenu, QFileDialog, QAbstractItemView, QMessageBox, QWidget)
def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

from PyQt5.uic import loadUiType

FORM_CLASS,_=loadUiType(resource_path("main2.ui"))

import sqlite3

class PandasModel_1(QAbstractTableModel):
    def __init__(self, df = pd.DataFrame(), parent=None):
        QAbstractTableModel.__init__(self, parent=None)
        self._df = df
        self.setChanged = False
        self.dataChanged.connect(self.setModified)

    def setModified(self):
        self.setChanged = True
#

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            try:
                return self._df.columns.tolist()[section]
            except (IndexError, ):
                return QVariant()
        elif orientation == Qt.Vertical:
            try:
                return self._df.index.tolist()[section]
            except (IndexError, ):
                return QVariant()

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if (role == Qt.EditRole):
                return self._df.values[index.row()][index.column()]
            elif (role == Qt.DisplayRole):
                return self._df.values[index.row()][index.column()]
        return None

    def setData(self, index, value, role):
        row = self._df.index[index.row()]
        col = self._df.columns[index.column()]
        print(row)
        print(col)
        print(value)

        self._df.values[index.row()][index.column()] = value
        self.dataChanged.emit(index, index)
        return True

    def rowCount(self, parent=QModelIndex()):
        return len(self._df.index)

    def columnCount(self, parent=QModelIndex()):
        return len(self._df.columns)

    def sort(self, column, order):
        colname = self._df.columns.tolist()[column]
        self.layoutAboutToBeChanged.emit()
        self._df.sort_values(colname, ascending= order == Qt.AscendingOrder, inplace=True)
        self._df.reset_index(inplace=True, drop=True)
        self.layoutChanged.emit()

class Main(QMainWindow, FORM_CLASS):
    def __init__(self,parent=None):
        super(Main,self).__init__(parent)
        app = QApplication([])
        app.setStyle('Fusion')
        self.history1_data = QTableView()
        self.model = PandasModel_1()
        self.history1_data.setModel(self.model)
        self.history1_data.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.history1_data.setSelectionBehavior(self.history1_data.SelectRows)
        self.history1_data.setSelectionMode(self.history1_data.SingleSelection)
        self.setupUi(self)
        self.Handel_Buttons()

    def Handel_Buttons(self):
        self.loadhist_btn.clicked.connect(self.GET_DATA) # this is for sqlite
#        self.corr_btn_1.clicked.connect(self.getCorr)
        self.load_file_btn.clicked.connect(self.loadFile) # this is for csv then pandas

    def GET_DATA(self):
        db = sqlite3.connect(resource_path("parts.db")) # Connect to Sqlite3 database ad fill GUI table with data
        cursor = db.cursor()
        command = ''' SELECT * from Superstore2csv '''
        result = cursor.execute(command)
        self.table1.setRowCount(0)
        for row_number, row_data in enumerate(result):
            self.table1.insertRow(row_number)
            for column_number, data in enumerate(row_data):
                self.table1.setItem(row_number, column_number, QTableWidgetItem(str(data)))
    def loadFile(self):
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open File", "", "CSV Files (*.csv)");
        self.pathLE1.setText(fileName)
        df = pd.read_csv(fileName)
        self.model = PandasModel_1(df)
        self.history1_data.setModel(self.model)
        self.history1_data.selectRow(0)
        self.save_file_btn_1.clicked.connect(self.Event1) # update dataframe

    def Event1(self):
        print(self.model.setChanged)
        if  self.model.setChanged == True:
            print(self.table.df)
        else:
            print("nothing changed. goodbye")

    def dataframe_output(self):

        print('\nUpdated DataFrame:')
        print(self.df_table)

def main():
    app = QApplication(sys.argv)
    window = Main()
    window.show()
    app.exec_()



if __name__ == '__main__':
    main()

标签: pandaspyqt5

解决方案


columns返回列的标签;默认情况下,它们是表示列索引的整数,但是如果您使用字符串,则显然不能将它们用于values,因为它是基于索引的数组。

在任何情况下,都不需要使用数据帧索引,因为 QModelIndex 已经提供了它们,您应该使用这些参数。

self._df.values[index.row()][index.column()] = value

推荐阅读