Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python QDataWidgetMapper和验证_Python_Qt_Pyside - Fatal编程技术网

Python QDataWidgetMapper和验证

Python QDataWidgetMapper和验证,python,qt,pyside,Python,Qt,Pyside,我有一个有几列的树状视图。我使用QDataWidgetMapper将每个列与侧栏上的几个小部件中的一个连接起来。可以通过双击树状视图中的单元格或使用侧边栏上的小部件来更改数据 我的一列包含需要验证的字符串数据。我创建了一个自定义委托,并将其附加到树视图和数据小部件映射器。它有一个QRegExpValidator,用于防止用户键入时输入无效。此外,在setModelData()中,一旦用户按下“Enter”键,它将进行不同的验证检查。对于树状视图,此委托工作正常。对于映射的QLineEdit,存在

我有一个有几列的树状视图。我使用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,因为我无法让它读取来自代理的一个。以下是从_uinit__;()更新的行:

  • 如果委托中的数据检查失败,我将使用原始值调用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
    
  • 据我了解:

  • QDataWidgetMapper
    用于将模型数据映射到现有小部件。因此,正如您所提到的,从未调用委托方法
    createEditor
    。说明了另一种方法:
    QDataWidgetMapper
    与视图一起使用,而不是使用委托方法
    createEditor
    。另一种方法是为侧边栏创建视图,向其注册代理(以便视图调用
    createEditor
    ),并共享
    tableView
    的选择机制。看
  • 如果要按照上述建议创建边栏视图,则可以通过还原编辑器值来处理
    setModelData
    返回false的事件
  • 我必须承认,我对模型视图还比较陌生。我很想听听其他人的意见。这是一个很好的问题

    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