Я использую виджет QLineEdit для ввода адресов электронной почты и настроил QRegExpValidor для проверки ввода.
Валидатор работает до тех пор, пока предотвращает ввод символов, не разрешенных в QRegExp, но, как ни странно, он позволяет вводить промежуточный ввод либо нажатием клавиши ввода, либо запуском сигнала завершения редактирования.
Я проверил правильный возврат валидатора (промежуточный или приемлемый).
Проверка документации PyQt5 показывает, что промежуточное состояние валидатора не мешает смещению фокуса на другой виджет. Кроме того, он останавливает срабатывание сигналов editFinished и returnPressed, поэтому пользователь может ввести неправильный адрес, поскольку он частично проходит RegExp. Ссылка: https://doc.qt.io/qt-5/qlineedit.html#acceptableInput-prop
Я смог решить свои проблемы, удалив валидатор из виджета QLineEdit и поместив метод checkValidator, связанный с курсоромPositionChanged виджета QLineEdit, отбрасывая последний введенный символ, когда он неприемлем, и возвращая фокус обратно к QLineEdit, когда он проверяет промежуточное значение. Он работает нормально, но когда фокус был сброшен, другие сигналы на других виджетах срабатывали по одному. На мгновение я обрабатываю это, проверяя, имеет ли отправитель фокус в начале методов (см. lookForFile)
Несмотря на то, что я мог справиться с этой проблемой, я очень благодарен всем, кто объясняет мне, как правильно использовать RegExpValidator и почему сброс фокуса запускает другие сигналы ни с того ни с сего.
def setUI(self):
self.setWindowTitle("EMail Settings")
self.setModal(True)
rx = QRegExp(r"[a-z0-9_%]+@[a-z0-9%_]+\.[a-z0-9%_]{3,3}")
lblAddress = QLabel("EMail Address")
self.lineAddress = QLineEdit(self)
self.mailValidator = QRegExpValidator(rx, self.lineAddress)
#self.lineAddress.setValidator(self.mailValidator)
self.lineAddress.cursorPositionChanged.connect(self.checkValidator)
self.lineAddress.returnPressed.connect(self.checkValidator)
lblPassword = QLabel("Password")
self.linePwd = QLineEdit()
self.linePwd.setEchoMode(QLineEdit.PasswordEchoOnEdit)
lblOauth2 = QLabel("Oauth2 Token")
self.lineOauth = QLineEdit()
pushOauth = QPushButton("...")
pushOauth.setObjectName("token")
pushOauth.clicked.connect(self.lookForFile)
pushOauth.setFixedWidth(30)
@pyqtSlot()
def checkValidator(self):
self.lineAddress.blockSignals(True)
v = self.mailValidator.validate(self.lineAddress.text(), len(self.lineAddress.text()))
if v[0] == 0:
self.lineAddress.setText(self.lineAddress.text()[:-1])
elif v[0] == 1:
self.lineAddress.setFocus()
elif v[0] == 2:
pass
print("validates", v)
self.lineAddress.blockSignals(False)
@pyqtSlot()
def lookForFile(self):
try:
if not self.sender().hasFocus():
return
baseDir = "C"
obj = self.sender()
if obj.objectName() == "Draft":
capt = "Email Draft"
baseDir = os.getcwd() + "\\draft"
fileType = "Polo Management Email (*.pad)"
dialog = QFileDialog(self, directory=os.getcwd())
dialog.setFileMode(QFileDialog.Directory)
res = dialog.getExistingDirectory()
elif obj.objectName() == "token":
capt = "Gmail Outh2 token File"
fileType = "Gmail token Files (*.json)"
baseDir = self.lineOauth.text()
res = QFileDialog.getOpenFileName(self, caption=capt, directory=baseDir, filter=fileType)[0]
fileName = res
if obj.objectName() == "Draft":
self.lineDraft.setText(fileName)
elif obj.objectName() == "tokenFile":
self.lineOauth.setText(fileName)
except Exception as err:
print("settings: lookForFile", err.args)
Надеюсь ответить на запрос @eyllanesc и Qmusicmante с помощью этого минимального воспроизводимого примера. Я меняю регулярное выражение на простое, позволяющее использовать строку строчных букв az, за которой следует точка и еще три символа нижнего регистра.
Я имею в виду, что валидатор не позволяет пользователю вводить неправильный ввод. В примере разрешены xxxzb.ods, но также разрешены, например, xxxzb или xxxzb.o. Короче говоря, не позволяя пользователю вводить неправильный ввод.
Это мой минимальный воспроизводимый пример:
class CheckValidator(QDialog):
def __init__(self, parent=None):
super().__init__()
self.parent = parent
self.setUI()
def setUI(self):
self.setWindowTitle("EMail Settings")
self.setModal(True)
rx = QRegExp(r"[a-z]+\.[a-z]{3}")
lblAddress = QLabel("Check Line")
self.lineAddress = QLineEdit()
self.mailValidator = QRegExpValidator(rx, self.lineAddress)
self.lineAddress.setValidator(self.mailValidator)
self.lineAddress.cursorPositionChanged[int, int].connect(lambda
oldPos, newPos: self.printValidator(newPos))
lblCheck = QLabel("Check")
lineCheck = QLineEdit()
formLayout = QFormLayout()
formLayout.addRow(lblAddress, self.lineAddress)
formLayout.addRow(lblCheck, lineCheck)
self.setLayout(formLayout)
@pyqtSlot(int)
def printValidator(self, pos):
print(self.mailValidator.validate(self.lineAddress.text(), pos))
if __name__ == '__main__':
app = QApplication(sys.argv)
tst = CheckValidator()
tst.show()
app.exec()
!#$%&'*+-/=?^_`{|}~
), и оно не разрешает многоуровневые домены (@ кое-что.co.uk). См. Как проверить адрес электронной почты с помощью регулярного выражения?. - person musicamante   schedule 08.04.2021