python - pyqt5 标签可见性未隐藏的问题
问题描述
我试图隐藏我在未填写行编辑时创建的错误标签(“*”),然后在填写时让它消失,但我的程序不一致。
它不起作用的一个例子:
将三个插槽留空,然后按“添加学生”按钮 - 每个插槽旁边都会出现一个红色星号。
在第一个(“开始日期”)行编辑中输入任何内容,然后按“添加学生”按钮 - 红色星号将消失。
对名字重复 2,但红色星号不会消失。
对姓氏重复 2,但红色星号也不会消失。
import sys
import datetime
from PyQt5 import QtWidgets as qt, QtGui, QtCore
class AddStudent(qt.QMainWindow):
def __init__(self):
# Set the window to the dimensions of the Screen
super().__init__()
screenSize = qt.QDesktopWidget().screenGeometry(-1)
self.height = screenSize.height()
self.width = screenSize.width()
self.setGeometry(0, 0, self.width, self.height)
self.setStyleSheet("QLabel {font: 16pt}")
# Add the buttons, line edits, and table
self.foundError = False
self.setup()
# Display the GUI
self.setWindowTitle("Add Student")
def setup(self):
self.startingDateLabel()
self.firstNameLabel()
self.lastNameLabel()
self.addStudentButton()
# Button Declarations
def startingDateLabel(self):
self.dateLabel = qt.QLabel(self)
self.dateLabel.setText("Starting Date:")
# (L/R, U/D, L/R, U/D)
self.dateLabel.setGeometry(158, 150, 262, 50)
self.dateLineEdit = qt.QLineEdit(self)
date = str(datetime.date.today()).split("-")
today = date[1] + "/" + date[2] + "/" + date[0]
self.dateLineEdit.setText(today)
self.dateLineEdit.setGeometry(435, 155, 250, 50)
def firstNameLabel(self):
self.firstName = qt.QLabel(self)
self.firstName.setText("First Name:")
self.firstName.setGeometry(205, 250, 215, 50)
self.firstNameLineEdit = qt.QLineEdit(self)
self.firstNameLineEdit.setGeometry(435, 255, 250, 50)
def lastNameLabel(self):
self.lastName = qt.QLabel(self)
self.lastName.setText("Last Name:")
self.lastName.setGeometry(208, 350, 212, 50)
self.lastNameLineEdit = qt.QLineEdit(self)
self.lastNameLineEdit.setGeometry(435, 355, 250, 50)
def addStudentButton(self):
self.addStudent = qt.QPushButton(self)
self.addStudent.setText("Add Student")
self.addStudent.setGeometry(800, 1500, 150, 50)
self.addStudent.clicked.connect(self.addStudentButtonPressed)
self.addStudent.show()
def addStudentButtonPressed(self):
# Check to make sure that everything that needs to be filled out is filled out
self.errorFound = False
# Check the starting date
if (self.dateLineEdit.text() == ""):
self.error1 = qt.QLabel(self)
self.error1.setText("*")
self.error1.setStyleSheet('color: red')
self.error1.setGeometry(715, 155, 30, 50)
self.error1.show()
self.errorFound = True
else:
try:
self.error1.hide()
self.errorFound = False
except:
self.errorFound = False
# Check the first name slot
if (self.firstNameLineEdit.text() == ""):
self.error2 = qt.QLabel(self)
self.error2.setText("*")
self.error2.setStyleSheet('color: red')
self.error2.setGeometry(715, 255, 30, 50)
self.error2.show()
self.errorFound = True
else:
try:
self.error2.hide()
self.errorFound = False
except:
self.errorFound = False
# Check the last name slot
if (self.lastNameLineEdit.text() == ""):
self.error3 = qt.QLabel(self)
self.error3.setText("*")
self.error3.setStyleSheet('color: red')
self.error3.setGeometry(715, 355, 30, 50)
self.error3.show()
self.errorFound = True
else:
try:
self.error3.hide()
self.errorFound = False
except:
self.errorFound = False
# Run the window
app = qt.QApplication(sys.argv)
window = AddStudent()
window.show()
sys.exit(app.exec())
解决方案
这是另一种可能的解决方案;虽然它可能看起来比CodeSurgeon 提出的另一个复杂一点,但在我看来,它的可扩展性要高得多——而且在某种程度上更优雅。
这里要注意的是嵌入了子 QLabel 的 QLineEdit 的子类,该子类仅在字段中有文本时才可见。添加了resizeEvent
覆盖以确保在调整窗口大小时始终正确放置“*”标签。
这种方法有很多优点,但最重要的是子类化“主”小部件,而不是创建一个嵌入其他小部件的新小部件,而是自动公开其所有方法和属性。
因此,所有这些都允许您添加任意数量的 [文本] 字段,并且仅当每个字段中都有一些内容时才启用/禁用提交按钮。
import sys
from PyQt5 import QtCore, QtWidgets
class MyLineEdit(QtWidgets.QLineEdit):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# the "invalid" label *has* to be a child of this QLineEdit
self.invalidLabel = QtWidgets.QLabel('*', self)
self.invalidLabel.setStyleSheet('color: red;')
spacing = 2
# get default margins and re-set them accordingly
self.leftMargin, self.topMargin, self.rightMargin, self.bottomMargin = self.getContentsMargins()
self.rightMargin += self.invalidLabel.minimumSizeHint().width() + spacing
self.setContentsMargins(self.leftMargin, self.topMargin, self.rightMargin + spacing, self.bottomMargin)
self.textChanged.connect(self.setValid)
self.setValid(self.text())
def setValid(self, text):
self.invalidLabel.setVisible(not bool(text))
def isValid(self):
return bool(self.text())
def resizeEvent(self, event):
self.invalidLabel.setGeometry(self.width() - self.rightMargin, self.topMargin,
self.invalidLabel.minimumSizeHint().width(), self.height() - self.topMargin - self.bottomMargin)
class MyApp(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setup()
def setup(self):
self.form = QtWidgets.QGroupBox("Add Student")
self.setCentralWidget(self.form)
self.formLayout = QtWidgets.QFormLayout()
self.form.setLayout(self.formLayout)
self.fields = []
self.create_field('Starting Date:', defaultValue=QtCore.QDate.currentDate().toString('MM/dd/yyyy'))
self.create_field('First Name:')
self.create_field('Last Name:')
self.create_submit_button()
def create_field(self, label, defaultValue=''):
field = MyLineEdit(defaultValue)
self.fields.append(field)
field.defaultValue = field.text()
self.formLayout.addRow(label, field)
field.textChanged.connect(self.checkFields)
def create_submit_button(self):
self.submitButton = QtWidgets.QPushButton('Add Student')
self.formLayout.addRow(self.submitButton)
self.submitButton.clicked.connect(self.submit)
self.submitButton.setEnabled(False)
self.checkFields()
def checkFields(self):
self.submitButton.setEnabled(all(field.isValid() for field in self.fields))
def submit(self):
# doSomething([field.text() for field in self.fields)
for field in self.fields:
field.setText(field.defaultValue)
app = QtWidgets.QApplication(sys.argv)
w = MyApp()
w.show()
sys.exit(app.exec_())
正如已经指出的那样,由于您使用的是行编辑,因此您应该真正考虑验证日期内容(因为可以在那里输入任何内容)。
更好的解决方案是使用 QDateEdit,但您需要像我对 QLineEdit 所做的那样对其进行子类化并创建一个单独的create
函数,显然它将在提交“验证”中“忽略”,因为 QDateEdit 字段自动允许有效的日期输入.
否则你可以使用 QValidator,但这将是 a** 中众所周知的痛苦,主要是因为 QDateTime 已经通过 using 提供了验证和漂亮的日历视图setCalendarPopup(True)
,并且通过正则表达式验证日期真的很烦人。
推荐阅读
- angular - How to implement debounceTime the Angular way
- python - python readline和异步打印
- reporting-services - SSRS With A Disclaimer Page
- elasticsearch - How to delete ElasticSearch snapshots by prefix
- here-api - 我无法从平台获取 trafficService
- python - 切换语言时 /i18n/setlang/ 出现 OperationalError
- python - 如何在 Odoo v12 中将数据从销售订单行发送到发票行?
- java - Java 无法解析的日期异常
- angular - 如何从组件访问正文
- c# - 为什么我不能在带有 inline { get; 的变量之前使用 [Space(15)] 放; }?