Проверка содержимого QLineEdit после взаимодействия с другими объектами

Мне нужно ввести число в поле QLineEdit,
в моём случае это возраст человека (диапазон от 18 до 80 лет).

После ввода и переключения фокуса на другой объект, например на другое поле или нажатия на кнопку, нужно чтобы программа проверяла, какое число введено, если оно меньше 18 или больше 80, вывести всплывающее окно с ошибкой и поставить фокус на это поле, если всё в порядке ничего не делать.

        from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
        QMetaObject, QObject, QPoint, QRect,
        QSize, QTime, QUrl, Qt)
    from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
        QFont, QFontDatabase, QGradient, QIcon,
        QImage, QKeySequence, QLinearGradient, QPainter,
        QPalette, QPixmap, QRadialGradient, QTransform)
    from PySide6.QtWidgets import (QApplication, QGridLayout, QHBoxLayout, QLabel,
        QLineEdit, QMainWindow, QSizePolicy, QWidget)
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            if not MainWindow.objectName():
                MainWindow.setObjectName(u"MainWindow")
            MainWindow.resize(371, 118)
            self.centralwidget = QWidget(MainWindow)
            self.centralwidget.setObjectName(u"centralwidget")
            self.gridLayout = QGridLayout(self.centralwidget)
            self.gridLayout.setObjectName(u"gridLayout")
            self.horizontalLayout = QHBoxLayout()
            self.horizontalLayout.setSpacing(0)
            self.horizontalLayout.setObjectName(u"horizontalLayout")
            self.label = QLabel(self.centralwidget)
            self.label.setObjectName(u"label")
    
            self.horizontalLayout.addWidget(self.label)
    
            self.lineEdit = QLineEdit(self.centralwidget)
            self.lineEdit.setObjectName(u"lineEdit")
    
            self.horizontalLayout.addWidget(self.lineEdit)
    
    
            self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
    
            self.horizontalLayout_2 = QHBoxLayout()
            self.horizontalLayout_2.setSpacing(0)
            self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
            self.label_2 = QLabel(self.centralwidget)
            self.label_2.setObjectName(u"label_2")
    
            self.horizontalLayout_2.addWidget(self.label_2)
    
            self.lineEdit_2 = QLineEdit(self.centralwidget)
            self.lineEdit_2.setObjectName(u"lineEdit_2")
    
            self.horizontalLayout_2.addWidget(self.lineEdit_2)
    
    
            self.gridLayout.addLayout(self.horizontalLayout_2, 1, 0, 1, 1)
    
            MainWindow.setCentralWidget(self.centralwidget)
    
            self.retranslateUi(MainWindow)
    
            QMetaObject.connectSlotsByName(MainWindow)
        # setupUi
    
        def retranslateUi(self, MainWindow):
            MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
            self.label.setText(QCoreApplication.translate("MainWindow", u"\u0412\u043e\u0437\u0440\u0430\u0441\u0442", None))
            self.label_2.setText(QCoreApplication.translate("MainWindow", u"\u0427\u0442\u043e-\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0435", None))
        # retranslateUi
        import sys
    from test import *
    
    class Test(QMainWindow):
        def __init__(self):
            super(Test, self).__init__()
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = Test()
        window.show()
    
        sys.exit(app.exec())

Попытался сделать через eventFilter, всё получается, но есть проблема в фокусе. Если вернуть фокус, то курсора на нём не видно, так же хотелось бы сделать выделение всего текста, но selectAll() не работает.

    from PySide6 import QtWidgets, QtCore, QtGui

class QTApp(QtWidgets.QWidget):
    def __init__(self):
        super(QTApp, self).__init__()

        self.LE_sample_input_01 = QtWidgets.QLineEdit()
        self.LE_sample_input_02 = QtWidgets.QLineEdit()

        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.LE_sample_input_01)
        layout.addWidget(self.LE_sample_input_02)

        self.LE_sample_input_01.installEventFilter(self)

    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.FocusOut and QtGui.QFocusEvent.reason(event) == QtCore.Qt.MouseFocusReason:
            if obj is self.LE_sample_input_01:
                self.LE_sample_input_01.setFocus()
                try:
                    age = int(self.LE_sample_input_01.text())
                    if age < 18 or age > 80:
                        error = QtWidgets.QMessageBox()
                        error.setWindowTitle('Ошибка возраста')
                        error.setText('Возраст введён неверно (от 18 до 80 лет)')
                        error.setIcon(QtWidgets.QMessageBox.Warning)
                        error.addButton('Ок',QtWidgets.QMessageBox.AcceptRole)
                        error.exec()
                        obj.setFocus()
                        obj.selectAll()
                except:
                    print('Ошибка')
        return QtWidgets.QWidget.eventFilter(self,obj,event)


if __name__ == "__main__":
    app = QtWidgets.QApplication()
    qt_app = QTApp()
    qt_app.show()
    app.exec()

Ответы (1 шт):

Автор решения: S. Nick

Возможный вариант решения, выглядит примерно так:

import sys
'''
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
    QMetaObject, QObject, QPoint, QRect,
    QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
    QFont, QFontDatabase, QGradient, QIcon,
    QImage, QKeySequence, QLinearGradient, QPainter,
    QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QGridLayout, QHBoxLayout, QLabel,
    QLineEdit, QMainWindow, QSizePolicy, QWidget)
'''

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *

# ??? from test import *


# !!! +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
class LineEdit(QtWidgets.QLineEdit):                                         # !!! +++

#!!! signal = Signal()                                         # !!! PySide6
    signal = pyqtSignal()                                      # !!! PyQt5

    def __init__(self, parent=None):
        super(LineEdit, self).__init__(parent)
        
    def focusInEvent(self, event):
        #print(f'focus In Event ')  
        self.setInputMask('00;#')
    
    def focusOutEvent(self, event):                                         # !!! +++
        #print(f'focus Out Event')  
        self.signal.emit()                                                  
# !!! +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(371, 118)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        
        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName(u"gridLayout")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setSpacing(10)
        
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.label = QLabel(self.centralwidget)
        self.label.setObjectName(u"label")
        self.horizontalLayout.addWidget(self.label)

#        self.lineEdit = QLineEdit(self.centralwidget)
# !!! +++
        self.lineEdit = LineEdit(self.centralwidget)                         # !!! +++
        
        self.lineEdit.setObjectName(u"lineEdit")
        self.horizontalLayout.addWidget(self.lineEdit)
        self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
        
        self.horizontalLayout_2 = QHBoxLayout()
        self.horizontalLayout_2.setSpacing(10)
        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
        self.label_2 = QLabel(self.centralwidget)
        self.label_2.setObjectName(u"label_2")
        self.horizontalLayout_2.addWidget(self.label_2)

        self.lineEdit_2 = QLineEdit(self.centralwidget)
        self.lineEdit_2.setObjectName(u"lineEdit_2")
        self.horizontalLayout_2.addWidget(self.lineEdit_2)
        self.gridLayout.addLayout(self.horizontalLayout_2, 1, 0, 1, 1)

        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
        self.label.setText(QCoreApplication.translate("MainWindow", u"\u0412\u043e\u0437\u0440\u0430\u0441\u0442", None))
        self.label_2.setText(QCoreApplication.translate("MainWindow", u"\u0427\u0442\u043e-\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0435", None))
    

class Test(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(Test, self).__init__()
        self.setupUi(self)
        
        self.label.setMinimumWidth(120)
        self.lineEdit.setMaxLength(2)
        self.lineEdit.setAlignment(QtCore.Qt.AlignCenter)

        self.lineEdit.signal.connect(self.editing_finished)            # !!! +++
        self.lineEdit.editingFinished.connect(self.editing_finished)   # !!! +++

    def editing_finished(self):
        text = self.lineEdit.text()
        if not text:
            self.lineEdit.signal.disconnect(self.editing_finished)
            msg = QMessageBox.information(self, 
                'Внимание', 
                'Заполните поле Возраст'
            )
            self.lineEdit.setFocus(True)
            self.lineEdit.signal.connect(self.editing_finished)
            return
            
        age = int(text) 
        if 18 <= age <= 80:
            self.lineEdit_2.setFocus(True)
        else:
            self.lineEdit.signal.disconnect(self.editing_finished)
            msg = QMessageBox.information(self, 
                'Внимание', 
                f'Возраст (<b style="color: #f00;">{age}</b>) или меньше 18 или больше 80'
            )
            self.lineEdit.setFocus(True)
            self.lineEdit.signal.connect(self.editing_finished)
            return
            
    def closeEvent(self, event):
        self.lineEdit.signal.disconnect(self.editing_finished)
        self.lineEdit.editingFinished.disconnect(self.editing_finished)
  

if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
    window = Test()
    window.show()
    sys.exit(app.exec())

введите сюда описание изображения

→ Ссылка