Custom QAbstractItemDelegate with regex for QSqlTa

2019-09-07 03:50发布

问题:

I'm trying to create a custom delegate so I can use Regex to verify the data that's being entered into the table but for some reason, my code keeps throwing errors, is there a good structured example?

These are the two errors I'm currently getting, and when I fix the AttributeError: 'QLineEdit' object has no attribute 'set' by using QLineEdit.setText my regular expression doesn't work and it allows any value to be added in.

Traceback (most recent call last):
  File "F:\Computing\Program V3\stockGui.py", line 23, in setEditorData
    editor.set(text)
AttributeError: 'QLineEdit' object has no attribute 'set'
Traceback (most recent call last):
  File "F:\Computing\Program V3\stockGui.py", line 29, in setModelData
    model.setData(index, QVariant(editor.text()))
NameError: name 'QVariant' is not defined






class ProductDelegate(QtSql.QSqlRelationalDelegate):
    def __init__(self):
        super().__init__()      

    def createEditor(self, parent, option, index):
        if index.column() == 1:
            editor = QtGui.QLineEdit(parent)
            regex = QtCore.QRegExp(r"(?:[A-Z|\s]+)")
            validator = QtGui.QRegExpValidator(regex,parent)
            editor.setValidator(validator)
            return editor
        else:
            return QtSql.QSqlRelationalDelegate.createEditor(self, parent, option, index)

    def setEditorData(self, editor, index):
        if index.column() == 1:
            text = index.model().data(index, QtCore.Qt.DisplayRole)
            editor.set(text)
        else:
            QtSql.QSqlRelationalDelegate.setEditorData(self, editor,index)

    def setModelData(self, editor, model, index):
        if index.column() == 1:
            model.setData(index, QVariant(editor.text()))
        else:
            QtSql.QSqlRelationalDelegate.setModelData(self, editor, model, index)

回答1:

As you've discovered, setText doesn't do any validatation. So, instead, use insert:

    text = index.model().data(index, QtCore.Qt.DisplayRole)
    editor.clear()
    editor.insert(text)

The other error is caused simply because you did not import QVariant, and so you can't use it. The easiest fix is to just omit it altogether (PyQt will automatically convert to arguments to a QVariant wherever it's appropriate):

    model.setData(index, editor.text())

(NB: if you're using Python 3, then, by default, QVariant is always automatically converted both to and from the equivalent Python types).



回答2:

The above solution did not work for me.

This solution worked for me: http://nullege.com/codes/show/src@p@y@PyQt4-HEAD@examples@tools@settingseditor@settingseditor.py/626/PyQt4.QtGui.QRegExpValidator

    # This ensure that validation passes.
    text = editor.text()
    validator = editor.validator()
    if validator is not None:
        state, text = validator.validate(text, 0)
        if state != QtGui.QValidator.Acceptable:
            return

class Delegate(QtSql.QSqlRelationalDelegate):
"""
Delegate class handles the delegate. This allows for custom editing within
the GUI. QtSql.QSqlRelationalDelegate is being subclassed to support custom editing.

Methods that are being overridden are:
    createEditor
    setEditorData
    setModelData
"""


def __init__(self, parent = None):
    """Class constructor."""

    super(Delegate, self).__init__(parent)


def createEditor(self, parent, option, index):
    """
    This creates the editors in the delegate, which is reimplemented from
    QAbstractItemDelegate::createEditor(). It returns the widget used to edit
    the item specified by index for editing. The parent widget and style option
    are used to control how the editor widget appears.

    """

    column = index.column()
    if column == 1:
        editor = QtGui.QLineEdit(parent)
        regex = QtCore.QRegExp(r"[a-zA-Z][a-zA-Z0-9_]{3,60}")
        validator = QtGui.QRegExpValidator(regex,parent)
        editor.setValidator(validator)
        return editor

    # Else return the base editor. This will handle all other columns.
    else:
        return super(AppDelegate, self).createEditor(parent, option, index)


def setEditorData(self, editor, index):
    """
     Once the editor has been created and given to the view, the view calls
     setEditorData(). This gives the delegate the opportunity to populate the
     editor with the current data, ready for the user to edit.

    Sets the contents of the given editor to the data for the item
    at the given index.

    Note that the index contains information about the model being used.

    The base implementation does nothing.
    If you want custom editing you will need to reimplement this function.
    """

    column = index.column()

    # Get the data value from the model.
    text = index.model().data(index, QtCore.Qt.DisplayRole).toString()

    # Set the editors text to be the text from the model.
    if column == 1:
        editor.setText(text)


    # Else return the base setEditorData method.
    # This is not strictly needed because in flags the ID column is set
    # to be selectable only so it should never call setEditorData.
    else:
        return super(AppDelegate, self).setEditorData(self, editor, index)


def setModelData(self, editor, model, index):
    """
    Sets the data for the item at the given index in the model
    to the contents of the given editor. The base implementation does
    nothing.
    If you want custom editing you will need to reimplement this method.

    If the user confirms their edit the editor's data must be written
    back to the model. The model will then notify the views that the item
    has changed, and those views that are showing the item
    will request fresh data to display.

    In each case we simply retrieve the value from the appropriate editor,
    and call setData (), passing the values as QVariants.
    """

    column = index.column()

    # Test if the editor has been modified.
    if not editor.isModified():
        return

    # This ensure that validation passes.
    text = editor.text()
    validator = editor.validator()
    if validator is not None:
        state, text = validator.validate(text, 0)
        if state != QtGui.QValidator.Acceptable:
            return

    if column == 1:
        # Call model.setData and set the data to the text in the QLineEdit.
        # After the user confirms the edit then set the model data to the
        # new user input.
        model.setData(index, QtCore.QVariant(editor.text()))

    # else return the base setModelData method.
    else:
        super(AppDelegate, self).setModelData(self, editor, model, index)