Я вставил данные в подкласс QAbstractListModel и отобразил их с QListView и QTableView
изменения (удаление строки) отображаются в QListView сразу, но в QTableView, только если выбрано табличное представление
подгруппированная модель содержит метод setData с self.dataChanged.emit(index, index) внутри, поэтому он должен обновляться.
почему QTableView не обновляется сразу?

#!/usr/bin/env python

"""
minimum code to run a model view

"""



import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg


class ViewModel(qtc.QAbstractListModel):
    def __init__(self, input_data=None):
        super().__init__()
        self.input_data = input_data or []




    # naming of rows ,columns static !!
    def headerData(self, section, orientation, role):
        if role == qtc.Qt.DisplayRole:
            if orientation == qtc.Qt.Horizontal:


                return "dude" # todo dynamic labeling
            else:

                return "leboswki"  # todo dynamic labeling



    def data(self, index, role):

        if role == qtc.Qt.DisplayRole:
            row = index.row() # == wie liste[row] der index

            item = self.input_data[row]
            return item




    def rowCount(self, index): # parameter inside is needed !

        return len(self.input_data)



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



    def setData(self, index, value, role):

        if role == qtc.Qt.EditRole:
            row = index.row()
            if index.isValid():
                self.input_data[row] = value
                self.dataChanged.emit(index, index)
                return True
            else:
                return False


    def removeRows(self, position, rows, parent=qtc.QModelIndex()):
        self.beginRemoveRows(parent, position, position + rows-1)

        for i in range(rows):
            value = self.input_data[position]
            self.input_data.remove(value)

        self.endRemoveRows()
        return True





class MainWindow(qtw.QWidget):
    def __init__(self):
        super().__init__()

        # View
        list_view = qtw.QListView()
        self.model = ViewModel(input_data=["text1", "text2", "text3", "text4"])
        list_view.setModel(self.model)


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


        # widgets
        self.deleate_row_button = qtw.QPushButton("deleate rows")

        # layout
        qvboxlayout = qtw.QVBoxLayout()
        qvboxlayout.addWidget(list_view)
        qvboxlayout.addWidget(table_view)
        qvboxlayout.addWidget(self.deleate_row_button)
        self.setLayout(qvboxlayout)
        self.show()

        # function
        self.deleate_row_button.clicked.connect(lambda: self.model.removeRows(-1, 1))


if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    w = MainWindow()
    sys.exit(app.exec_())


1
Sator 18 Апр 2020 в 12:59

1 ответ

Лучший ответ

Хотя в Python вы можете получить доступ к отрицательным индексам, но этого не происходит в Qt, вызывающем ошибку. Решение состоит в том, чтобы преобразовать отрицательные индексы в положительные. С другой стороны, не удаляйте строки по их значению (self.input_data.remove(value)), поскольку, если бы у него было 2 строки с одинаковым текстом, могла бы возникнуть ошибка.

def rowCount(self, index=qtc.QModelIndex()):
    return 0 if index.isValid() else len(self.input_data)
def removeRows(self, position, rows, parent=qtc.QModelIndex()):
    position = (position + self.rowCount()) if position < 0 else position
    start = position
    end = position + rows - 1
    self.beginRemoveRows(parent, start, end)
    del self.input_data[start : end + 1]
    self.endRemoveRows()
    return True
0
eyllanesc 18 Апр 2020 в 12:47