QLineEdit使用QRegExpValidator编辑意外行为

2024-09-30 14:37:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用QLineEdit小部件输入电子邮件地址,并设置了一个QRegExpValidor来验证输入

验证器正在尽可能地防止输入QRegExp中不允许的字符,但有趣的是,它允许通过按下enter键或触发“editingfinished”信号来输入中间输入

我验证了验证器的返回是否正确(中间或可接受)

检查PyQt5文档,确认验证器的中间状态不会阻止焦点更改为另一个小部件。此外,它会停止触发editingFinished和returnedPressed信号,因此用户可能会输入错误的地址,直到部分进入RegExp。 参考:https://doc.qt.io/qt-5/qlineedit.html#acceptableInput-prop

我可以通过从QLineEdit小部件中删除验证器,并放置一个方法“checkValidator”,链接到QLineEdit小部件的cursorPositionChanged,将不可访问时输入的最后一个字符分割,并在验证Intermediate时将焦点设置回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的请求。我将正则表达式更改为一个简单的正则表达式,允许一个小写a-z字符串后跟一个点和三个以上的小写字符

我的意图是验证程序不允许用户输入错误的输入。该示例允许使用“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()

Tags: textselfobjif信号部件defrx
1条回答
网友
1楼 · 发布于 2024-09-30 14:37:58

我找到了一个解决方案,我把它贴在这里,这样的情况可能会帮助别人。 首先,我从QLineEdit小部件中删除QRegExpValidator。原因是QLineEdit仅在QRegExpValidator返回QValidator.Acceptable时才会激发editingFinished(我们需要它),而验证程序存在

然后,我们设置一个由QlineEdit小部件的“cursorPositionchanged”信号触发的方法。在这个方法中,我们使用QRegExpValidator确定最后输入的字符是否有效。如果不是,我们就把它移除

最后,我使用RegEx exactMatch函数设置了由“editingFinished”信号触发的方法,以确定条目是否有效。如果不是,我们给用户清除条目或返回小部件继续输入数据的选项。使用的正则表达式仅用于测试目的,有关电子邮件验证检查@Musicamante注释的更多信息

这就是所涉及的代码:

    def setUI(self):
        ................
        ................
        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.cursorPositionChanged[int, int].connect(lambda oldPos, 
              newPos: self.checkValidator(newPos))
        self.lineAddress.editingFinished.connect(lambda : self.checkRegExp(rx))

    @pyqtSlot(int)
    def checkValidator(self, pos):
        v = self.mailValidator.validate(self.lineAddress.text(), pos ))
        if v[0] == 0:
            self.lineAddress.setText(self.lineAddress.text()[:-1])

    @pyqtSlot(QRegExp)
    def checkRegExp(self, rx):
        if not rx.exactMatch(self.lineAddress.text()) and self.lineAddress.text():
            if QMessageBox.question(self, "Leave the Address field",
               "The string entered is not a valid email address! \n" 
               "Do you want to clear the field?", QMessageBox.Yes|QMessageBox.No) == 
                QMessageBox.Yes:
                self.lineAddress.clear()
            else:
                self.lineAddress.setFocus()

相关问题 更多 >