Как связать кнопку с полем ввода в PyQt?

Подскажите, как можно связать кнопку с полем ввода, чтобы по нажатию кнопки бралась информация из связанного с ней поля ввода?

Понятно, что можно написать функцию по обработке этого значения и связать её с кнопкой с помощью clicked.connect(), но у меня много однотипных полей и кнопок, нужно чтобы кнопка выполняла функцию для соответствующего поля, а гору однотипного кода плодить не хочется.

main.py:


from PyQt6 import QtCore, QtGui, QtWidgets


class Ui_test(object):
    def setupUi(self, test):
        test.setObjectName("test")
        test.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(parent=test)
        self.centralwidget.setObjectName("centralwidget")
        self.form1 = QtWidgets.QLineEdit(parent=self.centralwidget)
        self.form1.setGeometry(QtCore.QRect(40, 30, 113, 22))
        self.form1.setObjectName("form1")
        self.btn1 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn1.setGeometry(QtCore.QRect(180, 30, 93, 28))
        self.btn1.setObjectName("btn1")
        self.form2 = QtWidgets.QLineEdit(parent=self.centralwidget)
        self.form2.setGeometry(QtCore.QRect(40, 80, 113, 22))
        self.form2.setObjectName("form2")
        self.form3 = QtWidgets.QLineEdit(parent=self.centralwidget)
        self.form3.setGeometry(QtCore.QRect(40, 130, 113, 22))
        self.form3.setObjectName("form3")
        self.form4 = QtWidgets.QLineEdit(parent=self.centralwidget)
        self.form4.setGeometry(QtCore.QRect(40, 180, 113, 22))
        self.form4.setObjectName("form4")
        self.btn2 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn2.setGeometry(QtCore.QRect(180, 70, 93, 28))
        self.btn2.setObjectName("btn2")
        self.btn3 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn3.setGeometry(QtCore.QRect(180, 130, 93, 28))
        self.btn3.setObjectName("btn3")
        self.btn4 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn4.setGeometry(QtCore.QRect(180, 180, 93, 28))
        self.btn4.setObjectName("btn4")
        test.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(parent=test)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        self.menubar.setObjectName("menubar")
        test.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(parent=test)
        self.statusbar.setObjectName("statusbar")
        test.setStatusBar(self.statusbar)

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

    def retranslateUi(self, test):
        _translate = QtCore.QCoreApplication.translate
        test.setWindowTitle(_translate("test", "MainWindow"))
        self.btn1.setText(_translate("test", "PushButton"))
        self.btn2.setText(_translate("test", "PushButton"))
        self.btn3.setText(_translate("test", "PushButton"))
        self.btn4.setText(_translate("test", "PushButton"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    test = QtWidgets.QMainWindow()
    ui = Ui_test()
    ui.setupUi(test)
    test.show()
    sys.exit(app.exec())


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

Автор решения: S. Nick

Исходя из того как составлена форма, можно предложить такой вариант:

'''
from PyQt6 import QtCore, QtGui, QtWidgets
'''
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_test(object):
    def setupUi(self, test):
        test.setObjectName("test")
        test.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(parent=test)
        self.centralwidget.setObjectName("centralwidget")
        self.form1 = QtWidgets.QLineEdit(parent=self.centralwidget)
        self.form1.setGeometry(QtCore.QRect(40, 30, 113, 22))
        self.form1.setObjectName("form1")
        self.btn1 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn1.setGeometry(QtCore.QRect(180, 30, 93, 28))
        self.btn1.setObjectName("btn1")
        self.form2 = QtWidgets.QLineEdit(parent=self.centralwidget)
        self.form2.setGeometry(QtCore.QRect(40, 80, 113, 22))
        self.form2.setObjectName("form2")
        self.form3 = QtWidgets.QLineEdit(parent=self.centralwidget)
        self.form3.setGeometry(QtCore.QRect(40, 130, 113, 22))
        self.form3.setObjectName("form3")
        self.form4 = QtWidgets.QLineEdit(parent=self.centralwidget)
        self.form4.setGeometry(QtCore.QRect(40, 180, 113, 22))
        self.form4.setObjectName("form4")
        self.btn2 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn2.setGeometry(QtCore.QRect(180, 70, 93, 28))
        self.btn2.setObjectName("btn2")
        self.btn3 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn3.setGeometry(QtCore.QRect(180, 130, 93, 28))
        self.btn3.setObjectName("btn3")
        self.btn4 = QtWidgets.QPushButton(parent=self.centralwidget)
        self.btn4.setGeometry(QtCore.QRect(180, 180, 93, 28))
        self.btn4.setObjectName("btn4")
        test.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(parent=test)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        self.menubar.setObjectName("menubar")
        test.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(parent=test)
        self.statusbar.setObjectName("statusbar")
        test.setStatusBar(self.statusbar)

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

    def retranslateUi(self, test):
        _translate = QtCore.QCoreApplication.translate
        test.setWindowTitle(_translate("test", "MainWindow"))
        self.btn1.setText(_translate("test", "PushButton"))
        self.btn2.setText(_translate("test", "PushButton"))
        self.btn3.setText(_translate("test", "PushButton"))
        self.btn4.setText(_translate("test", "PushButton"))


class Window(QtWidgets.QMainWindow, Ui_test):
    def __init__(self):
        super(Window, self).__init__()
        self.setupUi(self)
        
        self.btn1.clicked.connect(
            lambda ch, btn = self.btn1: self.btn_clicked(btn))
        self.btn2.clicked.connect(
            lambda ch, btn = self.btn2: self.btn_clicked(btn))
        self.btn3.clicked.connect(
            lambda ch, btn = self.btn3: self.btn_clicked(btn))
        self.btn4.clicked.connect(
            lambda ch, btn = self.btn4: self.btn_clicked(btn))
            
    def btn_clicked(self, btn):
        btn_objectName = btn.objectName()
        if btn_objectName == "btn1":
            print(f'{btn_objectName}: {self.form1.text()}')  
        elif btn_objectName == "btn2":
            print(f'{btn_objectName}: {self.form2.text()}')    
        if btn_objectName == "btn3":
            print(f'{btn_objectName}: {self.form3.text()}')
        if btn_objectName == "btn4":
            print(f'{btn_objectName}: {self.form4.text()}')            


if __name__ == "__main__":
    import sys
    
    app = QtWidgets.QApplication(sys.argv)
    test = Window()
    test.show()
    sys.exit(app.exec())

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

Я не понимаю что у вас будет дальше, поэтому засомневался в оптимальности вашей формы. Но это уже другая история.


Update:

Это близко к тому, что я хочу. А если представить, что таких кнопок сотня?
Неужели все нужно перечислять в условии?
Может быть в Qt Designer есть встроенная функция подобной связки?

Вы можете использовать setattr() / getattr() для динамического создания переменных, используя строку, как показано ниже:

'''
from PyQt6 import QtCore, QtGui, QtWidgets
'''
from PyQt5 import QtCore, QtGui, QtWidgets


class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.centralwidget = QtWidgets.QWidget()
        self.setCentralWidget(self.centralwidget)
        
        flay = QtWidgets.QFormLayout(self.centralwidget)

        self.texts = [
            ["name", "какое-то имя"], 
            ["address", "какой-то адрес"], 
            ["phone", "какой-то телефон"],
            ["email", "какой-то email"],
            ["Заметки", "какие-то Заметки"],
            # ...
        ]
        
        for i, text in enumerate(self.texts):
            self.btn = QtWidgets.QPushButton(f'{text[0]}: ', self)
            self.btn.clicked.connect(lambda ch, i=i: self.create_txt(i))    
            self.lineEdit = QtWidgets.QLineEdit(self, placeholderText=text[1])
            flay.addRow(self.btn, self.lineEdit)

            # Атрибут класса создается с помощью setattr()                    # !!!
            obj = setattr(self, f"btn_{i+1:0>2}", self.btn)                   # !
            setattr(self, f"lineEdit_{i+1:0>2}", self.lineEdit)               # !

    def create_txt(self, i):
        obj_btn = getattr(self, f"btn_{i+1:0>2}")                             # !!!
        obj_edit = getattr(self, f"lineEdit_{i+1:0>2}")                       # !!!
        print(f'{obj_btn.text()}: {obj_edit.text()}')             
        

if __name__ == "__main__":
    import sys
    
    app = QtWidgets.QApplication(sys.argv)
    test = Window()
    test.show()
    sys.exit(app.exec())

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

→ Ссылка