Как создать несколько атрибутов класса, которые являются объектами другого класса в цикле, и затем в цикле вызвать методы для этих атрибутов?

Требуется создать несколько лэблов с разными именами по нажатию кнопки, установить различные параметры для лэйблов, и не дублировать код.

У меня получилось сделать это только так:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1139, 843)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(140, 270, 121, 71))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(310, 270, 131, 71))
        self.pushButton_2.setObjectName("pushButton_2")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1139, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.all_labels_added = False
        self.pushButton.clicked.connect(self.add_labels)
        self.pushButton_2.clicked.connect(self.delete_labels)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "add"))
        self.pushButton_2.setText(_translate("MainWindow", "delete"))


    def add_labels(self):
        if not self.all_labels_added:
            self.label_1 = QtWidgets.QLabel(self.centralwidget)
            self.label_1.setGeometry(QtCore.QRect(450, 440, 21, 21))
            self.label_1.setStyleSheet("Border: solid black;\n"
                                                  "Border-width: 2px;\n"
                                                  "Background-color: white;")
            self.label_1.setText("")
            self.label_1.setAlignment(QtCore.Qt.AlignCenter)
            self.label_1.setTextInteractionFlags(QtCore.Qt.TextEditable | QtCore.Qt.TextSelectableByMouse)
            self.label_1.setObjectName("label_1")
            self.label_1.raise_()
            self.label_1.show()

            self.label_2 = QtWidgets.QLabel(self.centralwidget)
            self.label_2.setGeometry(QtCore.QRect(490, 440, 21, 21))
            self.label_2.setStyleSheet("Border: solid black;\n"
                                       "Border-width: 2px;\n"
                                       "Background-color: white;")
            self.label_2.setText("")
            self.label_2.setAlignment(QtCore.Qt.AlignCenter)
            self.label_2.setTextInteractionFlags(QtCore.Qt.TextEditable | QtCore.Qt.TextSelectableByMouse)
            self.label_2.setObjectName("label_2")
            self.label_2.raise_()
            self.label_2.show()

            self.label_3 = QtWidgets.QLabel(self.centralwidget)
            self.label_3.setGeometry(QtCore.QRect(530, 440, 21, 21))
            self.label_3.setStyleSheet("Border: solid black;\n"
                                       "Border-width: 2px;\n"
                                       "Background-color: white;")
            self.label_3.setText("")
            self.label_3.setAlignment(QtCore.Qt.AlignCenter)
            self.label_3.setTextInteractionFlags(QtCore.Qt.TextEditable | QtCore.Qt.TextSelectableByMouse)
            self.label_3.setObjectName("label_3")
            self.label_3.raise_()
            self.label_3.show()
            self.all_labels_added = True

    def delete_labels(self):
        try:
            self.label_1.deleteLater()
            self.label_2.deleteLater()
            self.label_3.deleteLater()
            self.all_labels_added = False
        except:
            pass



if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Пробовал делать так:

def add_labels(self):
    for i in range(1, 4):
    setattr(self, f'label_{i}', QtWidgets.QLabel(self.centralwidget))

Смотрел в дебагере, атрибуты создаются, но я не могу придумать как вызвать методы для этих атрибутов, которые являются объектами класса QLabel, для установки, параметров по типу setStyleSheet и тд., так же в цикле. Или можно как-то по другому сделать, тот же функционал?


Ответы (1 шт):

Автор решения: S. Nick
  1. НИКОГДА НЕ ИЗМЕНЯЙТЕ код, сгенерированный Qt Designer, НИКОГДА.
    Создайте другой класс, который наследуется от соответствующего виджета, и используйте созданный класс для его заполнения.

  2. Абсолютное позиционирование не очень хорошая практика, всегда используйте менеджеры компоновки.

  3. Обычно вашу задумку реализуют созданием класса виджета, которые вы собираетесь создавать динамически и передавать ему какие-то значения.


main.py

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1139, 843)
        
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(140, 270, 121, 71))
        self.pushButton.setObjectName("pushButton")
        
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(310, 270, 131, 71))
        self.pushButton_2.setObjectName("pushButton_2")
        
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1139, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "add"))
        self.pushButton_2.setText(_translate("MainWindow", "delete"))


class Label(QLabel):
    labelSignal = pyqtSignal(object)
    
    def __init__(self, text, bgd, clr, parent=None):
        super().__init__(parent)
        
        self.parent = parent
        
        self.setFocusPolicy(Qt.StrongFocus)
        self.setObjectName(f"label_{text}")

        self.setText(f"{text}")
        self.setStyleSheet(f"""
            QLabel {{
                background-color: {bgd}; 
                border: 1px solid blue; 
                color: {clr}; 
                font: bold italic 20pt 'Times New Roman';
            }}
            QLabel::focus {{
                border: 2px solid red;
                background-color: black;
                color: red;
            }}
        """)        
        
        self.setMinimumHeight(30) 
        self.setMinimumWidth(30)  

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.labelSignal.emit(self)
        super().mousePressEvent(e)  
        

class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.all_labels_added = False
        self.pushButton.clicked.connect(self.add_labels)
        self.pushButton_2.clicked.connect(self.delete_labels)
        
        self.layout = QGridLayout(self.centralwidget)
        self.layout.addWidget(self.pushButton, 1, 0, 1, 1, 
            alignment=Qt.AlignLeft | Qt.AlignBottom)
        self.layout.addWidget(self.pushButton_2, 2, 0, 1, 1, 
            alignment=Qt.AlignLeft | Qt.AlignTop)
        
        self.list_label = [
            ['A', '#FF9551', '#781C68'],
            ['B', '#FEDB39', '#005555'],
            ['C', '#0F3D3E', '#ECB390'],
        ]

    def add_labels(self):
        if not self.all_labels_added:
            for i, lbl  in enumerate(self.list_label):        
                label = Label(*lbl, self)
                label.labelSignal.connect(self.press_label)
                self.layout.addWidget(label, 1, i+1, 2, 1, alignment=Qt.AlignCenter)

    def delete_labels(self):
        labels =  self.findChildren(QLabel)
        if labels:
            for label in labels:
               label.hide() 
            self.all_labels_added = False
            
    def press_label(self, obj):            
        print(f'Label: objectName={obj.objectName()}')

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
#    MainWindow = QtWidgets.QMainWindow()
#    ui = Ui_MainWindow()
#    ui.setupUi(MainWindow)
#    MainWindow.show()

    w = MainWindow()
    w.resize(400, 300)
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка