首页 > 解决方案 > pyqt5 标签可见性未隐藏的问题

问题描述

我试图隐藏我在未填写行编辑时创建的错误标签(“*”),然后在填写时让它消失,但我的程序不一致。

它不起作用的一个例子:

  1. 将三个插槽留空,然后按“添加学生”按钮 - 每个插槽旁边都会出现一个红色星号。

  2. 在第一个(“开始日期”)行编辑中输入任何内容,然后按“添加学生”按钮 - 红色星号将消失。

  3. 对名字重复 2,但红色星号不会消失。

  4. 对姓氏重复 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())

标签: pythonpython-3.xpyqtpyqt5

解决方案


这是另一种可能的解决方案;虽然它可能看起来比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),并且通过正则表达式验证日期真的很烦人。


推荐阅读