Как создать несколько атрибутов класса, которые являются объектами другого класса в цикле, и затем в цикле вызвать методы для этих атрибутов?
Требуется создать несколько лэблов с разными именами по нажатию кнопки, установить различные параметры для лэйблов, и не дублировать код.
У меня получилось сделать это только так:
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 шт):
НИКОГДА НЕ ИЗМЕНЯЙТЕ код, сгенерированный Qt Designer, НИКОГДА.
Создайте другой класс, который наследуется от соответствующего виджета, и используйте созданный класс для его заполнения.Абсолютное позиционирование не очень хорошая практика, всегда используйте менеджеры компоновки.
Обычно вашу задумку реализуют созданием класса виджета, которые вы собираетесь создавать динамически и передавать ему какие-то значения.
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_())
