PyQt6. Как получить доступ к конкретному виджету в списке сформированным циклом?
Создал в Qt Designer MainWindow, в котором располагается QScrollArea.
Также имеется отдельный виджет, который помещается циклом внутри QScrollArea.
На виджете расположены label и pushButton.
Задача следующая: при нажатии на кнопку, текст лейбла в том же виджете должен измениться.
В моем случае изменяется только текст последнего виджета в списке не зависимо от того какая кнопка была нажата.
Вот код главного окна: main_window.py
Вот код виджета: widget.py
Вот скрипт запускающий программу:
from PyQt6.QtWidgets import QApplication
from PyQt6 import QtWidgets
from mw import Ui_MainWindow
from fr import Ui_Form
import sys
class Form(QtWidgets.QWidget, Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.vbox = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
class App(MainWindow, Form):
def __init__(self):
super().__init__()
self.stack_widget()
# здесь виджеты стакаются в scrollarea
def stack_widget(self):
for i in range(10):
self.form = Form()
self.form.pushButton.clicked.connect(lambda: self.change_label(self.form.pushButton.text()))
self.vbox.addWidget(self.form)
# здесь изменяется текст в виджете при нажатии на кнопку
def change_label(self, button):
self.form.label.setText(button)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = App()
window.show()
sys.exit(app.exec())
На ум приходят всевозможные словари, хранящие данные типа:
{<PyQt6.QtWidgets.QPushButton object at 0x000001465DF945E0>: <__main__.Form object at 0x000001465DF94430>}
или enumerate(), но все это кажется очевидно неправильными методами требующими кучу проверок.
Мне ясна суть того почему изменения происходят именно в последнем виджете, но как наиболее простым методом получить доступ к нужному виджету я никак не соображу. Помогите. Спасибо.
Ответы (1 шт):
Вам незачем в цикле при создании экземпляра класса Form
делать его атрибутом класса App.
Правильное использование функции lambda выглядит так:
form.pushButton.clicked.connect(
lambda ch, form=form, i=i: self.change_label(form, i))
а слот так:
def change_label(self, form, i):
form.label.setText(f'{form.pushButton.text()} {i}')
void QAbstractButton::clicked(bool checked = false)
main.py
import sys
#from PyQt6 import QtWidgets
from PyQt5 import QtWidgets
from mw import Ui_MainWindow
from fr import Ui_Form
class Form(QtWidgets.QWidget, Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.vbox = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
class App(MainWindow, Form):
def __init__(self):
super().__init__()
self.stack_widget()
# здесь виджеты стакаются в scrollarea
def stack_widget(self):
for i in range(10):
# self.form = Form()
form = Form()
form.pushButton.clicked.connect(
lambda ch, form=form, i=i: self.change_label(form, i))
self.vbox.addWidget(form)
# здесь изменяется текст в виджете при нажатии на кнопку
def change_label(self, form, i):
form.label.setText(f'{form.pushButton.text()} {i}')
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = App()
window.show()
sys.exit(app.exec())
mw.py
#from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(412, 265)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 392, 245))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout.addWidget(self.scrollArea)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
fr.py
#from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 41)
self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(Form)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "TextLabel"))
self.pushButton.setText(_translate("Form", "PushButton"))
