Search code examples
pythonqtpyqtmaya

pyQt pushButton connect creation within loop


I am new to pyqt (pyside in maya), please be nice to me :)

so the point is i want to generate many button via loop statement, something simmilar like below :

(5 button in a window - complete code - maya)

import PySide.QtCore as qc
import PySide.QtGui as qg
class simpleUI(qg.QDialog):
    def __init__(self):
        qg.QDialog.__init__(self)
        self.setWindowTitle('Simple UI')
        self.btn=[]
        for x in range(5) :
           self.btn.append(x)
           self.btn[x]= qg.QPushButton(self)
           self.btn[x].setText('this is btn number{0}'.format(x))
           self.btn[x].setGeometry(qc.QRect(0,100+(x*20), 100,20))
           self.btn[x].clicked.connect(lambda : self.notifyMe(x))
    def notifyMe(self,index):
        print index
dialog = simpleUI()
dialog.show()

as you see, I store button object in array, but the problem is when i want to connect btn signal with notifyMe function, every button always give x same value (x=4) , meanwhile in button.setText x succeed give unique incremental value, i can't figure it why..

Edit:

revisit this again after 6 years later, I wanna inform that I was always using partial rather than lambda, here is what I did on PySide2 / PyQt5:

import sys
from PySide2.QtWidgets import *
from functools import partial

class simpleUI:
    def __init__(self):
        app = QApplication()
        window = QMainWindow()
        layout = QVBoxLayout()

        for x in range(5):
            btn = QPushButton('this is btn number {0}'.format(x))
            btn.clicked.connect(partial(self.notifyMe, index=x))
            layout.addWidget(btn)
        widget = QWidget()
        widget.setLayout(layout)
        window.setCentralWidget(widget)
        #
        window.show()
        sys.exit(app.exec_())

    def notifyMe(self, index):
        print(index)

if __name__ == '__main__':
    simpleUI()

Solution

  • It is old problem with function in lambda - it doesn't get value from x when you declare function but when you click button. But when you click button then for-loop is over and x keeps last value - and this way all buttons use the same value. You have to use

    lambda a=x: self.notifyMe(a)