当表模型更新时,Qtableview 不会更新

时间:2021-07-08 00:00:50

标签: python model-view-controller pyqt5

我正在编写一个 gui 应用程序,用于将多个 Excel 文件处理为一个文件。主窗口显示一个表,用户可以在该表中添加或删除要收集到较大文件中的文件。每行将代表一个文件,其中包含用于不同参数的列(要从该文件中提取的数据。)我一直致力于为此目的实现 QAbstractTableModel,尽管我无法更新表视图,但效果很好.当一个新行被添加到我的数据数组中时,一个新行被添加到表视图中,但每一列都是空的。我不确定为什么会这样,因为我已经确认数据数组正在更新。示例:

class _tableModel(QAbstractTableModel):
    def __init__(self, data=None):
        QAbstractTableModel.__init__(self)

        self.data = data
        self.load_data(data)

    def load_data(self, data):
        self.input_files = data[:,0]
        self.input_sheets = data[:,1]

        self.column_count = 2
        self.row_count = len(self.input_sheets)

    def rowCount(self, parent=QModelIndex()):
        return self.row_count

    def columnCount(self, parent=QModelIndex()):
        return self.column_count

    def headerData(self, section, orientation, role):
        if role != Qt.DisplayRole:
            return None
        if orientation == Qt.Horizontal:
            return ("File", "Sheet")[section]
        else:
            return "{}".format(section)

    def data(self, index, role=Qt.DisplayRole):
        column = index.column()
        row = index.row()

        if role == Qt.DisplayRole:
            if column == 0:
                file = str(self.input_files[row])
                return file
            elif column == 1:
                return str(self.input_sheets[row])
        elif role == Qt.BackgroundRole:
            return QColor(Qt.white)
        elif role == Qt.TextAlignmentRole:
            return Qt.AlignRight

        return None

    def appendRowData(self, data):
        self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
        self.data = np.concatenate((self.data, data), axis=0)
        self.endInsertRows()


    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole:
            self.data[index.row()][index.column()] = value
            self.dataChanged.emit(index, index)
            return True

class Widget(QWidget):
    def __init__(self, data=None):
        QWidget.__init__(self)

        self.main_layout = QVBoxLayout()

        self.addFileButton = QPushButton('Add File')
        self.addFileButton.clicked.connect(self.addFileDialog)
        self.main_layout.addWidget(self.addFileButton)

        self.model = _tableModel(data)

        self.table_view = QTableView()
        self.table_view.setModel(self.model)

        self.horizontal_header = self.table_view.horizontalHeader()
        self.vertical_header = self.table_view.verticalHeader()
        self.horizontal_header.setSectionResizeMode(
                               QHeaderView.ResizeToContents
                               )
        self.vertical_header.setSectionResizeMode(
                             QHeaderView.ResizeToContents
                             )
        self.horizontal_header.setStretchLastSection(True)

        size = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

        size.setHorizontalStretch(1)
        self.table_view.setSizePolicy(size)
        self.main_layout.addWidget(self.table_view)

        self.setLayout(self.main_layout)

    def addFileDialog(self):
        self.fileWizard = QDialog()

        self.wiz_layout = QFormLayout()
        self.fileWizard.setLayout(self.wiz_layout)

        self.selectExcelFile = QPushButton('Select Excel File')
        self.selectExcelFile.clicked.connect(self.selectexcel)
        self.wiz_layout.addRow(self.selectExcelFile)

        self.selectedFileDisplay = QTextEdit()
        self.wiz_layout.addRow(self.selectedFileDisplay)

        self.sheet = QLineEdit()
        self.wiz_layout.addRow('Sheet Name: ', self.sheet)

        self.add_to_table = QPushButton('Add to File Table')
        self.wiz_layout.addWidget(self.add_to_table)
        self.add_to_table.clicked.connect(self._addTableEntry)

        self.fileWizard.show()

    def selectexcel(self):
        self.filename = QFileDialog.getOpenFileName(self)
        self.filename = self.filename[0]

        self.selectedFileDisplay.setText(self.filename)
        pass

    def _addTableEntry(self):
        row = self.model.rowCount()
        data = np.array([[self.filename, self.sheet.text()]])
        self.model.appendRowData(data)


class _mainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.generalLayout = QGridLayout()

        data = np.array([['File name here','Sheet name here']])
        self._centralWidget = Widget(data)
        self.setCentralWidget(self._centralWidget)
        self._centralWidget.setLayout(self.generalLayout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = _mainWindow()
    window.show()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:0)

rowCountcolumnCount 都必须是动态的,因为它们返回模型的当前范围。

您将这些值设置为静态值,因此,虽然模型“接受”行的插入(如视图中所示),但它无法访问它们,因为行数和列数不反映更新的模型尺寸。

    def rowCount(self, parent=QModelIndex()):
        return len(self.data[:,1])

请注意,您也不是更新 self.data,而是实际上替换了它。由于您将 self.input_files 用于 data(),因此可能会导致异常,因为这些数组实际上并未更新。

因此,您要么总是在任何具有正确切片的地方使用 self.data,要么使用 python 属性来访问 input_filesinput_sheets

class _tableModel(QAbstractTableModel):
    # ...
    @property
    def input_files(self):
        return self.data[:,0]
    # ...
相关问题