ASCII字符的QValidator保持无效

问题描述

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

以下是验证器的代码

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)

这是我的自定义lineEdit:

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

解决方法

一种选择是使用ASCII字符范围来验证其是否符合this answer中指出的内容:

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_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_())
,

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