我正在使用带有数据类作为项目的子类QAbstractTableModel 。每个数据类都包含一个带有list的字段“field1” ,我想在 listview 中显示它,并在我在 listview 中编辑或添加项目时自动更改它。
为此,我为QDataWidgetMapper设置了一个自定义委托,它将从该数据类中检索和设置值。这按我想要的方式工作。
我的问题是我想通过按下按钮向该列表视图添加其他项目,并让QDataWidgetMapper将它们自动添加到模型中。
这是我到目前为止所拥有的:
import sys
import dataclasses
from typing import List, Any
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
@dataclasses.dataclass()
class StorageItem:
field1: List[str] = dataclasses.field(default_factory=list)
class StorageModel(QAbstractTableModel):
def __init__(self, parent=None):
super().__init__(parent)
test = StorageItem()
test.field1 = ['Item °1', 'Item °2']
self._data: List[StorageItem] = [test]
def data(self, index: QModelIndex, role: int = ...) -> Any:
if not index.isValid():
return
item = self._data[index.row()]
col = index.column()
if role in {Qt.DisplayRole, Qt.EditRole}:
if col == 0:
return item.field1
else:
return None
def setData(self, index: QModelIndex, value, role: int = ...) -> bool:
if not index.isValid() or role != Qt.EditRole:
return False
item = self._data[index.row()]
col = index.column()
if col == 0:
item.field1 = value
self.dataChanged.emit(index, index)
print(self._data)
return True
def flags(self, index: QModelIndex) -> Qt.ItemFlags:
return Qt.ItemFlags(
Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
)
def rowCount(self, parent=None) -> int:
return len(self._data)
def columnCount(self, parent=None) -> int:
return len(dataclasses.fields(StorageItem))
class TestDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super().__init__(parent)
def setEditorData(self, editor: QWidget, index: QModelIndex) -> None:
if isinstance(editor, QListView):
data = index.model().data(index, Qt.DisplayRole)
editor.model().setStringList(data)
else:
super().setEditorData(editor, index)
def setModelData(
self, editor: QWidget,
model: QAbstractItemModel,
index: QModelIndex
) -> None:
if isinstance(editor, QListView):
data = editor.model().stringList()
model.setData(index, data, Qt.EditRole)
else:
super().setModelData(editor, model, index)
class CustomListView(QListView):
item_added = pyqtSignal(name='itemAdded')
def __init__(self, parent=None):
super().__init__(parent)
self.setModel(QStringListModel())
def add_item(self, item: str):
str_list = self.model().stringList()
str_list.append(item)
self.model().setStringList(str_list)
self.item_added.emit()
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
cent_widget = QWidget()
self.setCentralWidget(cent_widget)
# Vertical Layout
v_layout = QVBoxLayout()
v_layout.setContentsMargins(10, 10, 10, 10)
# Listview
self.listview = CustomListView()
v_layout.addWidget(self.listview)
# Button
self.btn = QPushButton('Add')
self.btn.clicked.connect(lambda: self.listview.add_item('New Item'))
v_layout.addWidget(self.btn)
cent_widget.setLayout(v_layout)
# Set Mapping
self.mapper = QDataWidgetMapper()
self.mapper.setItemDelegate(TestDelegate())
self.mapper.setSubmitPolicy(QDataWidgetMapper.AutoSubmit)
self.mapper.setModel(StorageModel())
self.mapper.addMapping(self.listview, 0)
self.mapper.toFirst()
self.listview.itemAdded.connect(self.mapper.submit)
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
if __name__ == '__main__':
main()
目前,我正在使用自定义ListView内部的信号itemAdded来手动提交QDataWidgetMapper。
有没有办法在CustomListView中做到这一点,而不使用自定义信号?不知何故,委托知道列表视图中的数据何时被编辑。添加新项目时如何触发相同的机制?