gpt4 book ai didi

python - 更新 Qt QDataWidgetMapper 上的数据,同时映射器索引保持不变

转载 作者:太空宇宙 更新时间:2023-11-03 21:44:13 24 4
gpt4 key购买 nike

我正在尝试映射 QAbstractTableModel 中的数据使用 QDataWidgetMapper 到自定义 View 。映射器工作正常,但映射的数据不会根据模型的变化自动更新。我需要手动更改 currentMapperIndex 以触发自定义 View 上的更改。

我试图最大限度地简化我的问题。

表格模型:

class TableModel(QAbstractTableModel):
def __init__(self, parent=None):
super(TableModel, self).__init__(parent)
self.columns = ['Col1', 'Col2']
self.datatable = []

def update(self, dataIn):
self.layoutAboutToBeChanged.emit()
self.datatable = dataIn
self.layoutChanged.emit()

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

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

def headerData(self, section, orientation, role=Qt.DisplayRole):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.columns[section].title()

def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole or role == Qt.EditRole:
row = self.datatable[index.row()]
column_key = self.columns[index.column()]
return row[column_key]
else:
return None

def setData(self, index, value, role=Qt.EditRole):
if not index.isValid() or role != Qt.EditRole:
return False
if self.datatable:
column_key = self.columns[index.column()]

self.datatable[index.row()][column_key] = value
self.dataChanged.emit(index, index, [])
return True
return True
<小时/>

自定义 View :

class CustomView(QWidget):
def __init__(self, parent=None):
super(CustomView, self).__init__(parent)

self.setupLayout()
self.spinboxMapperIndex.valueChanged.connect(self.changeMapperIndex)

def setModel(self, model):
self.mapper = QDataWidgetMapper()
self.mapper.setModel(model)
self.mapper.addMapping(self.lineEdit1, 0)
self.mapper.addMapping(self.lineEdit2, 1)
self.mapper.toFirst()

def changeMapperIndex(self, index):
self.mapper.setCurrentIndex(index)

def setupLayout(self):

self.spinboxMapperIndex = QSpinBox()

self.lineEdit1 = QLineEdit()
self.lineEdit2 = QLineEdit()

layout = QVBoxLayout()
layout.addWidget(self.spinboxMapperIndex)
layout.addWidget(self.lineEdit1)
layout.addWidget(self.lineEdit2)
self.setLayout(layout)
<小时/>

主要:

if __name__ == '__main__':
import sys
app = QApplication(sys.argv)

model = TableModel()

table = QTableView()
table.setModel(model)
table.show()

data = [ {'Col1': 11, 'Col2': 12},
{'Col1': 21, 'Col2': 22},
{'Col1': 31, 'Col2': 32}]
model.update(data)

view = CustomView()
view.setModel(model)
view.show()

newData = [ {'Col1': 111, 'Col2': 112},
{'Col1': 121, 'Col2': 122},
{'Col1': 131, 'Col2': 132}]
model.update(newData)

sys.exit(app.exec_())
<小时/>

通过运行上面的代码,可以看到 TableView 已使用新数据进行了很好的更新,而 CustomView 映射数据则不会更新,除非我手动更改旋转框以更改映射器索引。

关于QDataWidgetMapper我们可以阅读的文档:

Note that QDataWidgetMapper keeps track of external modifications. If the contents of the model are updated in another module of the application, the widgets are updated as well.

事实似乎并非如此...

任何帮助,即使是用 Qt C++ 形式编写的,我们都将不胜感激。

编辑:

根据 Kuba Ober 答案对 update 方法进行更改:

def update(self, dataIn):
self.beginResetModel()
self.datatable = dataIn
self.endResetModel()

最佳答案

您的模型没有履行每个 Qt 模型必须履行的契约(Contract)。部分问题在于模型,而不在于映射器。即,update 应该使用 beginResetModelendResetModel 方法。您不应该自己发出布局更改信号。事实上,您应该从模型中自己发出的唯一预定义信号是 dataChanged - 其他信号由 QAbstractItemModel 发出,以响应对 beginAction 的调用和endAction

重置模型后, View 应该重置当前索引 - 毕竟,在重置期间,模型实际上没有行 - 并且当前索引变得无效。因此,将以下内容添加到 CustomView.setModel:

self.model.modelReset.connect(self.mapper.toFirst)

可以说,也许映射器应该自己建立这样的连接,但它没有 - 因此你必须这样做。

关于python - 更新 Qt QDataWidgetMapper 上的数据,同时映射器索引保持不变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52609229/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com