pyqt5标签可见性未隐藏的问题

时间:2019-07-08 23:45:24

标签: python python-3.x pyqt pyqt5

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

一个不起作用的示例:

  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())

2 个答案:

答案 0 :(得分:0)

我对您的代码进行了以下更改:

  1. 只是一种代码风格的事情:我使用 snake case 作为变量和函数的名称。这是python代码的标准,PyQt是一个奇怪的例外(可能是由于从C ++代码库继承而来)。
  2. 我删除了self.errorFound的使用。正如我在评论中所暗示的那样,您永远不会在任何地方真正检查此值。如果只想知道任何个用户输入是否错误,最好只使用一个self.errorFound,但是一个布尔值不能告诉您哪个输入是错误的。错误。我只是在每次调用submit函数时检查用户输入的文本是否为空。
  3. 我使用QFormLayout类将小部件放置在屏幕上。这消除了键入小部件应属于的绝对坐标的所有猜测和数学运算。如果窗口太小,还可以防止小部件“消失”。这具有每行只能容纳两个小部件的限制。因此,我放弃了星号,只为相应的错误输入为QLabel着色。可以使用QGridLayout解决这个问题,或者,如果您喜欢QFormLayout,可以在每个字段中嵌套QHBoxLayout个对象。让我知道是否需要星号。

所有这些都没有了,下面是更新的代码:

import sys
import datetime
from PyQt5 import QtWidgets as qt, QtGui, QtCore

class MyApp(qt.QMainWindow):

    def __init__(self):
        super().__init__()
        screenSize = qt.QDesktopWidget().screenGeometry(-1)

        self.setup()
        self.setWindowTitle("My Awesome App!")

    def setup(self):
        self.form = qt.QGroupBox("Add Student")
        self.form_layout = qt.QFormLayout()

        self.create_date_input()
        self.create_first_name_input()
        self.create_last_name_input()
        self.create_submit_button()
        self.form.setLayout(self.form_layout)

        self.setContentsMargins(5, 5, 5, 5)
        self.setCentralWidget(self.form)

    def create_date_input(self):
        self.date_label = qt.QLabel("Starting Date:")
        self.date_entry = qt.QLineEdit(self)
        date = str(datetime.date.today()).split("-")
        today = date[1] + "/" + date[2] + "/" + date[0]
        self.date_entry.setText(today)

        self.form_layout.addRow(
            self.date_label, 
            self.date_entry,
        )

    def create_first_name_input(self):
        self.first_name_label = qt.QLabel("First Name:")
        self.first_name_entry = qt.QLineEdit(self)
        self.form_layout.addRow(
            self.first_name_label, 
            self.first_name_entry,
        )

    def create_last_name_input(self):
        self.last_name_label = qt.QLabel("Last Name:")
        self.last_name_entry = qt.QLineEdit(self)
        self.form_layout.addRow(
            self.last_name_label, 
            self.last_name_entry,
        )

    def create_submit_button(self):
        self.submit_button = qt.QPushButton(self)
        self.submit_button.setText("Add Student")
        self.submit_button.clicked.connect(self.submit)
        self.form_layout.addRow(self.submit_button)

    def submit(self):
        default_color = "color: black"
        error_color = "color: red"
        date_color = default_color
        first_name_color = default_color
        last_name_color = default_color

        #really should validate if this is a date, not just if it is empty
        if (self.date_entry.text() == ""):
            date_color = error_color

        if (self.first_name_entry.text() == ""):
            first_name_color = error_color

        if (self.last_name_entry.text() == ""):
            last_name_color = error_color

        self.date_label.setStyleSheet(date_color)
        self.first_name_label.setStyleSheet(first_name_color)
        self.last_name_label.setStyleSheet(last_name_color)

app = qt.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec())

答案 1 :(得分:0)

这是另一种可能的解决方案;尽管它似乎比CodeSurgeon提出的the other one复杂一些,但在我看来,它可以扩展得多-并且在某种程度上更优雅。

这里的捕获是QLineEdit的子类,该子类嵌入了子QLabel,只有在字段中有文本时,该子类才可见。添加了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已经通过使用setCalendarPopup(True)提供了验证和良好的日历视图,并且通过正则表达式验证日期确实很烦人。