0

我正在尝试构建一个 lineEdit 来检查非 ascii 字符。我使用 regex101 测试了 RegEx,它按预期工作。[:ascii:]似乎是一个 PCRE,因此应该与 QtRegExp 一起使用,对吧?但是,我的 QValidator 子类总是返回QValidator.State.Invalid(除非 lineEdit 在返回时为空QValidator.State.Intermediate),即使 lineEdit 清楚地只包含 ASCII 字符。

这是验证器的代码:

class ASCIIValidator (QtGui.QRegExpValidator):
    def __init__(self):
        super(ASCIIValidator, self).__init__()
        self.ASCII_REGEXP = QtCore.QRegExp()
        self.ASCII_REGEXP.setPattern(r'^[[:ascii:]]+$')
        self.ASCII_REGEXP.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.setRegExp(self.ASCII_REGEXP)

这是我的自定义行编辑:

class ULineEdit(QtWidgets.QLineEdit):
    focusChange = QtCore.Signal(bool)
    validated = QtCore.Signal(QtGui.QValidator.State)

    """Custom lineedit"""
    def __init__(self,
            defaultText: str = "",
            validators: list = [],
            completer: QtWidgets.QCompleter = None):

        super(ULineEdit, self).__init__()
        self.setText(defaultText)
        if completer is not None and isinstance(completer, QtWidgets.QCompleter):
            self.setCompleter(completer)
        self.validators = validators
        self.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)

        # Signals
        self.textChanged.connect(self.validateText)

    def addValidator(self, validator: QtGui.QValidator):
        if isinstance(validator, QtGui.QValidator):
            self.validators.append(validator)
            return
        elif isinstance(validator, list):
            self.validators.extend(validator)
            return

    def validateText(self):
        """Check validators and set the style"""
        if len(self.validators) > 0:
            for val in self.validators:
                testResult = val.validate(self.text(), 0)[0] #validate() returns a tuple
                invalidTests = []
                intermedTests = []
                acceptedTests = []
                print(testResult)
                if testResult == QtGui.QValidator.Invalid:
                    invalidTests.append(testResult)
                elif testResult == QtGui.QValidator.Intermediate:
                    intermedTests.append(testResult)
                elif testResult == QtGui.QValidator.Acceptable:
                    acceptedTests.append(testResult)
            if len(invalidTests) > 0:
                self.setStyleSheet(INVALID_STYLESHEET)
                self.validated.emit(QtGui.QValidator.Invalid)
                return QtGui.QValidator.Invalid
            
            if len(intermedTests) > 0: 
                self.setStyleSheet(LINEEDIT_STYLESHEET)
                self.validated.emit(QtGui.QValidator.Intermediate)
                return QtGui.QValidator.Intermediate

            if len(acceptedTests) > 0:
                self.setStyleSheet(VALID_STYLESHEET)
                self.validated.emit(QtGui.QValidator.Acceptable)
                return QtGui.QValidator.Acceptable
4

2 回答 2

0

一种选择是使用 ASCII 字符范围来验证它是否如本答案中所指出的那样:

import sys

from PySide2 import QtCore, QtGui, QtWidgets


class ASCIIValidator(QtGui.QRegExpValidator):
    def __init__(self, parent=None):
        super().__init__(parent)
        pattern = r"[^\x00-\x7F]+$"
        regex = QtCore.QRegExp(pattern)
        regex.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.setRegExp(regex)


class JoinValidator(QtGui.QValidator):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._validators = []

    @property
    def validators(self):
        return self._validators

    def add_validator(self, validator):
        self.validators.append(validator)

    def validate(self, _input, pos):
        texts = []
        positions = []
        final_state = QtGui.QValidator.Acceptable
        for validator in self.validators:
            state, new_input, new_pos = validator.validate(_input, pos)
            texts.append(new_input)
            positions.append(new_pos)
            if state == QtGui.QValidator.Invalid:
                final_state = QtGui.QValidator.Invalid
            elif (
                state == QtGui.QValidator.Intermediate
                and final_state != QtGui.QValidator.Invalid
            ):
                final_state = QtGui.QValidator.Intermediate
        new_pos = min(positions)
        new_input = min(texts, key=len)
        return final_state, new_input, new_pos


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.lineedit = QtWidgets.QLineEdit()

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.lineedit)

        self.validator = JoinValidator()
        self.validator.add_validator(ASCIIValidator())

        self.lineedit.textChanged.connect(self.handle_text_changed)

    def handle_text_changed(self):
        state, _, _ = self.validator.validate(
            self.lineedit.text(), self.lineedit.cursorPosition()
        )
        print(state)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = Widget()
    w.show()

    sys.exit(app.exec_())
于 2020-08-26T20:33:14.170 回答
0

您是否尝试过 r"[^\\x00-\\x7F]+$" 而不是 r"[^\x00-\x7F]+$" (带有双反斜杠)?它在 C++ 中工作。

于 2020-12-02T19:37:27.873 回答