Проблемы с скрытой видимостью ярлыка pyqt5 - PullRequest
1 голос
/ 09 июля 2019

Я пытаюсь скрыть метку ошибки ("*"), созданную мной, когда редактирование строки не заполнено, и затем оно исчезает при заполнении, но моя программа не соответствует.

Пример того, что он не работает:

  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 голосов
/ 10 июля 2019

Вот еще одно возможное решение;хотя он может показаться немного более сложным, чем другой , предложенный CodeSurgeon, на мой взгляд, он гораздо более расширяемый - и как-то более элегантный.

Подвох здесь подкласс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_())

Как уже указывалось, вам следует подумать о проверке содержимого даты (так как можно ввести что угодно), так как вы используете строкуedit.
Лучшее решение - использовать QDateEdit, но вам нужно будет создать его подкласс, как я это делал с QLineEdit, и создать отдельную функцию create, и, очевидно, она будет "проигнорирована" при отправке "проверки"поскольку поля QDateEdit автоматически допускают допустимые вводы даты.
В противном случае вы можете использовать QValidator, ноt это было бы общеизвестной болью в a **, главным образом потому, что QDateTime уже обеспечивает проверку и хорошее представление календаря с помощью setCalendarPopup(True), а проверка даты с помощью регулярного выражения действительно раздражает.

0 голосов
/ 09 июля 2019

Я внес следующие изменения в ваш код:

  1. Просто в стиле кода: я использовал случай змеи для имен переменных и функций. Это стандарт для кода 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())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...