我有一个包含多个列的树视图。我使用QDataWidgetMapper将每个列与侧栏上的几个小部件之一连接起来。可以通过双击树视图中的单元格或使用侧栏上的小部件来更改数据。
我的一个列包含需要验证的字符串数据。我创建了一个自定义委托,我附加到树视图和数据小部件映射器。它有一个QRegExpValidator,用于防止用户输入时输入无效。此外,在setModelData()中,一旦用户按下"输入",它就会有不同的验证检查。对于树视图,此委托工作正常。对于映射的QLineEdit,有两个问题:
我是以错误的方式解决这个问题吗?
这是一个简化的例子。为简单起见,我用列表视图替换了树视图:
class TestWidgetMapperValidate(QtGui.QMainWindow):
def __init__(self, parent=None):
super(TestWidgetMapperValidate, self).__init__(parent)
self.centralWidget = QtGui.QWidget()
self.setCentralWidget(self.centralWidget)
self.mainLayout = QtGui.QVBoxLayout(self.centralWidget)
# Set up the list view
self.listView = QtGui.QListView()
self.listModel = QtGui.QStringListModel(['aaa', 'bbb', 'ccc', 'ddd'])
self.listView.setModel(self.listModel)
# Set up the delegate
self.testDelegate = TestDelegate()
self.listView.setItemDelegateForColumn(0, self.testDelegate)
self.lineEdit = QtGui.QLineEdit()
self.mainLayout.addWidget(self.listView)
self.mainLayout.addWidget(self.lineEdit)
# Set up the QDataWidgetMapper
self.mapper = QtGui.QDataWidgetMapper()
self.mapper.setModel(self.listModel)
self.mapper.addMapping(self.lineEdit, 0)
self.mapper.setItemDelegate(self.testDelegate)
self.listView.selectionModel().currentChanged.connect(self.mapper.setCurrentModelIndex)
class TestDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent=None):
super(TestDelegate, self).__init__(parent)
def createEditor(self, parentWidget, option, qModelIndex):
editor = QtGui.QLineEdit(parentWidget)
nameRegex = QtCore.QRegExp('[a-zA-Z][a-zA-Z0-9_]+')
editor.setValidator(QtGui.QRegExpValidator(nameRegex))
return editor
def setEditorData(self, editor, qModelIndex):
value = qModelIndex.data(QtCore.Qt.DisplayRole)
editor.setText(value)
def setModelData(self, editor, model, qModelIndex):
if not editor.hasAcceptableInput():
return False
oldValue = qModelIndex.data(QtCore.Qt.DisplayRole)
newValue = editor.text()
if oldValue != newValue:
if newValue in model.stringList():
print 'That name already exists: {0}'.format(newValue)
return False
else:
return model.setData(qModelIndex, newValue)
else:
return True
(注意:我使用的是PySide和Python 2.7)
答案 0 :(得分:1)
这是我想出的。我不知道这是否是最佳解决方案,但它适用于我的情况。
我最后直接在我的行编辑中添加了一个QRegExpValidator,因为我无法从代理中读取它。以下是__init __()的更新行:
class TestWidgetMapperValidate(QtGui.QMainWindow):
def __init__(self, parent=rsui.getMayaMainWindow()):
# some code omitted here
self.lineEdit = QtGui.QLineEdit()
nameRegex = QtCore.QRegExp('[a-zA-Z][a-zA-Z0-9_]+')
self.lineEdit.setValidator(QtGui.QRegExpValidator(nameRegex))
如果数据未通过委托中的检查,我使用原始值调用setEditorData()以强制它返回旧值。这可以防止错误消息被打印两次。以下是TestDelegate类中更新的setModelData():
def setModelData(self, editor, model, qModelIndex):
if not editor.hasAcceptableInput():
return False
oldValue = qModelIndex.data(QtCore.Qt.DisplayRole)
newValue = editor.text()
if oldValue != newValue:
if newValue in model.stringList():
# The new value is not valid. Set the data back to the original value.
self.setEditorData(editor, qModelIndex)
print 'That name already exists: {0}'.format(newValue)
return False
else:
return model.setData(qModelIndex, newValue)
else:
return True
答案 1 :(得分:1)
据我所知:
QDataWidgetMapper
用于将模型数据映射到现有小部件。因此,正如您所提到的,永远不会调用委托方法createEditor
。换句话说:QDataWidgetMapper
使用委托方法createEditor
和视图一起使用代替。另一种方法是为侧边栏创建一个视图,用它注册您的委托(以便视图调用createEditor
)并共享tableView
的选择机制。见http://qt-project.org/doc/qt-5/model-view-programming.html#sharing-selections-among-views。setModelData
返回false的事件。我必须承认,我对模型视图相对较新。我有兴趣听到其他人的意见。这是一个很好的问题!