我有几列的树状视图。我使用QDataWidgetMapper将每一列与侧栏上的几个小部件之一连接。可以通过在树视图中双击一个单元格或使用侧栏上的小部件来更改数据。

我的其中一列包含需要验证的字符串数据。我创建了一个自定义委托,并将其附加到树视图和数据小部件映射器。它具有QRegExpValidator,以防止在用户键入时输入无效。同样,在setModelData()中,一旦用户按下“ Enter”,它将具有不同的验证检查。对于树视图,此委托可以正常工作。对于映射的QLineEdit,有两个问题:


QRegExpValidator不会被调用(可能是因为侧边栏小部件未使用createEditor());因此用户可以在QLineEdit中输入错误的输入。
如果在setModelData()期间数据未通过检查,则QLineEdit中的文本不会切换回原始文本。因此,当用户单击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)

最佳答案

这是我想出的。我不知道这是否是最好的解决方案,但它适用于我的情况。


我最终将QRegExpValidator直接添加到我的行编辑中,因为无法从委托中读取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

09-12 13:38