Валидация поля QLineEdit с элементами обратной связи для пользователя. Неожиданное изменение высоты QLineEdit
Пытаюсь написать валидацю полей с элементом обратной связи для пользователя.
Кнопка Save активируется в случае, если все поля заполнены корректно.
В качестве обратной связи для пользователя использую изменение цвета border в фокусном QLineEdit.
По какой-то причине изменение цвета границ меняет высоту (height) поля, делая его слегка меньше.
Визуально заметно на поле changed_line, лечится методом setFixedHeight() (исправлено в поле fixed_line).
Но хотелось бы понять причину такого поведения и как "вылечить" глобально, не фиксируя высоту для каждого поля.
Причем размер возвращается к исходному значению при смене поля и начале ввода информации.
main.py
import sys
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import pyqtSlot, QRegExp
from PyQt5.QtWidgets import *
class MainAppInterface(QMainWindow):
def __init__(self):
super().__init__()
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.setMinimumHeight(300)
self.setMinimumWidth(400)
self.resize(400, 300)
self.setWindowTitle("Test")
self.__main_app_build()
def __main_app_build(self):
self.line = QLineEdit()
self.line.setPlaceholderText("Default Line")
changed_re = QRegExp("[a-zA-Z0-9_.-]+")
self.changed_line = QLineEdit()
self.changed_line.setPlaceholderText("Changed Line")
self.changed_line.setValidator(QRegExpValidator(changed_re, self.changed_line))
self.changed_line.textChanged.connect(self.__save_enable)
fixed_re = QRegExp("^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$")
self.fixed_line = QLineEdit()
self.fixed_line.setPlaceholderText("Fixed Line (email field)")
self.fixed_line.setValidator(QRegExpValidator(fixed_re, self.fixed_line))
self.fixed_line.textChanged.connect(self.__save_enable)
self.fixed_line.setFixedHeight(22)
self.save_button = QPushButton("Save")
self.save_button.setDisabled(True)
g_layout = QGridLayout(self.centralWidget)
g_layout.addWidget(self.line, 0, 1)
g_layout.addWidget(self.changed_line, 1, 1)
g_layout.addWidget(self.fixed_line, 2, 1)
g_layout.addWidget(self.save_button, 3, 1)
@ pyqtSlot()
def __save_enable(self):
if self.changed_line.hasAcceptableInput() and self.fixed_line.hasAcceptableInput():
self.save_button.setDisabled(False)
else:
self.save_button.setDisabled(True)
self.changed_line.setStyleSheet("""
QLineEdit::focus {{
border-radius: 2px;
border: 1px outset;
border-color: {color};
}}
""".format(color="#00ff00" if self.changed_line.hasAcceptableInput() else "#ff0000"))
self.fixed_line.setStyleSheet("""
QLineEdit::focus {{
border-radius: 2px;
border: 1px outset;
border-color: {color};
}}
""".format(color="#00ff00" if self.fixed_line.hasAcceptableInput() else "#ff0000"))
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle("Fusion")
ex = MainAppInterface()
ex.show()
sys.exit(app.exec_())
Была мысль выставить в классе:
self.setStyleSheet("""
QLineEdit::focus {
height: 22px;
}""")
Но поведение изменилось в обратную сторону, поля в фокусе при изменении цвета рамки становятся слегка больше.
Ответы (1 шт):
Я так понял, что такое поведение border: 1px outset;
Попрбуйте поиграться с размерами.
Обратите внимание, что я пока экспериментировал,
добавил всем QLineEdit - objectName,
в любом случае, это не помешает,
а также добавил метод func() для наблюдения происходящего.
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import pyqtSlot, QRegExp
from PyQt5.QtWidgets import *
class MainAppInterface(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Test")
# self.setMinimumHeight(300)
# self.setMinimumWidth(400)
self.resize(400, 300)
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.__main_app_build()
def __main_app_build(self):
self.line = QLineEdit(objectName='line')
self.line.setPlaceholderText("Default Line")
changed_re = QRegExp("[a-zA-Z0-9_.-]+")
self.changed_line = QLineEdit(objectName='changed_line')
self.changed_line.setPlaceholderText("Changed Line")
self.changed_line.setValidator(
QRegExpValidator(changed_re, self.changed_line))
self.changed_line.textChanged.connect(self.__save_enable)
fixed_re = QRegExp("^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$")
self.fixed_line = QLineEdit(objectName='fixed_line')
self.fixed_line.setPlaceholderText("Fixed Line (email field)")
self.fixed_line.setValidator(
QRegExpValidator(fixed_re, self.fixed_line))
self.fixed_line.textChanged.connect(self.__save_enable)
# self.fixed_line.setFixedHeight(22)
self.save_button = QPushButton("Save")
self.save_button.setDisabled(True)
g_layout = QGridLayout(self.centralWidget)
g_layout.addWidget(self.line, 0, 1)
g_layout.addWidget(self.changed_line, 1, 1)
g_layout.addWidget(self.fixed_line, 2, 1)
g_layout.addWidget(self.save_button, 3, 1)
# vvv для отладки
QtCore.QTimer.singleShot(20 , self.func)
def func(self):
print(f'line = {self.line.size()}')
print(f'changed_line = {self.changed_line.size()}')
print(f'fixed_line = {self.fixed_line.size()}\n')
# ^^^ для отладки
@pyqtSlot(str) # <-----vvvv
def __save_enable(self, text):
self.func() # для отладки
if self.changed_line.hasAcceptableInput() and \
self.fixed_line.hasAcceptableInput():
self.save_button.setDisabled(False)
else:
self.save_button.setDisabled(True)
self.changed_line.setStyleSheet("""
#changed_line::focus {{
border-color: {color};
}}
""".format(color="#00ff00" if self.changed_line.hasAcceptableInput() \
else "#ff0000"))
self.fixed_line.setStyleSheet("""
#fixed_line::focus {{
border-color: {color};
}}
""".format(color="#00ff00" if self.fixed_line.hasAcceptableInput() \
else "#ff0000"))
self.func() # для отладки
QSS = '''
QLineEdit {
min-height: 22px; /* попробуйте изменить высоту */
max-height: 22px; /* попробуйте изменить высоту */
border-radius: 2px;
border: 1px outset;
border-color: #B8DFD8; /* попробуйте изменить color */
}
'''
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet(QSS)
app.setStyle("Fusion") # !!!
ex = MainAppInterface()
ex.show()
sys.exit(app.exec_())
