组合框更改时更新 QAbstractTableModel

问题描述

我正在尝试在更改组合框时更新我的​​模型。我有一个连接到更新模型的组合框的函数,但是来自 this question -“只要提供标准行为(访问 index.model()._data 不好),代表就应该使用模型的基本函数” .我还希望组合框的更改影响 QLineEdit 中出现的内容。

QItemDelegate:

class Delegate(QItemDelegate):

    def __init__(self):
        QItemDelegate.__init__(self)
        self.type_items = ["1","2"]

    def createEditor(self,parent,option,index):
        if index.column() == 0:
            comboBox = QComboBox(parent)
            for text in self.type_items:
                comboBox.addItem(text,(index.row(),index.column()))
                comboBox.currentIndexChanged.connect(lambda: self.comboBoxChanged(comboBox,index))
            return comboBox
        return super().createEditor(parent,index)

    # updates model but does not update view - shows what I want to happen
    def comboBoxChanged(self,comboBox,index):
        if comboBox.currentText() == "1":
            index.model()._data[index.row()][0] = "1"
            index.model()._data[index.row()][1] = "One"
        elif comboBox.currentText() == "2":
            index.model()._data[index.row()][0] = "2"
            index.model()._data[index.row()][1] = "Two"
        # self.dataChanged.emit(index,index) # can't call this here

QAbstractTableModel:

class TableModel(QAbstractTableModel):
    def __init__(self,data):
        super(TableModel,self).__init__()
        self._data = data

    def data(self,index,role):
        if role in (Qt.DisplayRole,Qt.EditRole):
            return self._data[index.row()][index.column()]

    def rowCount(self,index=None):
        return len(self._data)

    def columnCount(self,index=None):
        return len(self._data[0])

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

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

主要内容:

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

        localWidget = QWidget()

        self.table = QTableView()

        data = [["1","One"]]

        self.model = TableModel(data)
        self.table.setModel(self.model)
        self.table.setItemDelegate(Delegate())

        self.print_data = QPushButton("Print data")
        self.print_data.clicked.connect(self.printData)

        for row in range(self.model.rowCount()):
            for column in range(self.model.columnCount()):
                index = self.model.index(row,column)
                self.table.openPersistentEditor(index)

        layout_v = QVBoxLayout()
        layout_v.addWidget(self.table)
        layout_v.addWidget(self.print_data)
        localWidget.setLayout(layout_v)
        self.setCentralWidget(localWidget)
        self.show()

    def printData(self):
        print(self.model._data)

app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
  1. 如何在 qcombobox 中注册更改以正确更新模型? 和
  2. 如何使这触发 qlineedit 中的更改?

解决方法

最好使用现有的 setData 函数更新模型的数据,该函数提供了一个集中式界面,避免混淆错误和错误。

在你的情况下,你需要设置sibling索引的数据,它是下一列同一行的索引(不需要设置索引值本身,因为Qt是能够从组合中自动获取它,无论如何都应该在 setModelData() 中完成)。

    def comboBoxChanged(self,comboBox,index):
        if comboBox.currentText() == "1":
            value = "One"
        elif comboBox.currentText() == "2":
            value = "Two"
        sibling = index.sibling(index.row(),1)
        index.model().setData(sibling,value)

为了清楚起见,您的代码本来可以工作,但 dataChanged模型的信号,而不是委托,所以它应该是:

        index.model().dataChanged.emit(index,index)

但是,正如已经说过的,最好避免在模型中使用不同的方式来更改数据,尤其是在模型外部进行更改时。使用单个函数来处理这个问题的主要好处是,每当模型的结构和实现发生变化时,唯一需要检查的就是该函数调用的所有出现(以防列顺序发生变化) ,例如)。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...