问题描述
我正在尝试构建一个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 ++中工作。