Guido Guido - 5 months ago 14
Python Question

Python - Add buttons dyanmically to layout in PyQt

I am currently developing a desktop app using PyQt 5 and Python 3.5. Recently, I have encountered an issue while trying to dynamically add buttons to a layout. Here's what I am doing:

for i in range(len(movieList)):

movies[i][0] = QtWidgets.QLabel("Title: " + movieList[i][0])
movies[i][0].setGeometry(30, 50, 15, 20)
movies[i][0].setFont(self.movieTitleFont)

self.scrollLayout.addRow(movies[i][0])

#If the lenght is 3 it means it has 2 available resolutions
if len(movieList[i]) == 3:

movies[i][1] = [QtWidgets.QPushButton(movieList[i][1][1], self), QtWidgets.QPushButton(movieList[i][2][1], self)]

movies[i][1][0].clicked.connect(lambda: self.downloadMovie(movieList[i], movieList[i][1][1]))
movies[i][1][0].setGeometry(0, 0, 10, 20)

movies[i][1][1].clicked.connect(lambda: self.downloadMovie(movieList[i], movieList[i][2][1]))
movies[i][1][1].setGeometry(10, 0, 10, 20)

self.scrollLayout.addRow(movies[i][1][0])
self.scrollLayout.addRow(movies[i][1][1])

else:
movies[i][1] = [QtWidgets.QPushButton(movieList[i][1][1], self)]
movies[i][1][0].clicked.connect(lambda: self.downloadMovie(movieList[i], movieList[i][1][1]))
movies[i][1][0].setGeometry(30, 50, 10, 20)

self.scrollLayout.addRow(movies[i][1][0])


The problem I am having is that whenever all movies are loaded in my screen and I try to push one of the buttons to download said movie it will just take the last value "i" stored (in clicked.connect) so it will try to download the last movie shown. I have been working hardly to find a workaround to this but I haven't found the way.

Answer

I think if you change to partial then all will work fine

from functools import partial
...

for i in range(len(movieList)):

        movies[i][0] = QtWidgets.QLabel("Title: " + movieList[i][0])
        movies[i][0].setGeometry(30, 50, 15, 20)
        movies[i][0].setFont(self.movieTitleFont)

        self.scrollLayout.addRow(movies[i][0])

        #If the lenght is 3 it means it has 2 available resolutions
        if len(movieList[i]) == 3:

            movies[i][1] = [QtWidgets.QPushButton(movieList[i][1][1], self), QtWidgets.QPushButton(movieList[i][2][1], self)]

            movies[i][1][0].clicked.connect(partial( self.downloadMovie,movieList[i], movieList[i][1][1]))
            movies[i][1][0].setGeometry(0, 0, 10, 20)

            movies[i][1][1].clicked.connect(partial( self.downloadMovie,movieList[i], movieList[i][2][1]))
            movies[i][1][1].setGeometry(10, 0, 10, 20)

            self.scrollLayout.addRow(movies[i][1][0])
            self.scrollLayout.addRow(movies[i][1][1])

        else:
            movies[i][1] = [QtWidgets.QPushButton(movieList[i][1][1], self)]
            movies[i][1][0].clicked.connect(partial( self.downloadMovie,movieList[i], movieList[i][1][1]))
            movies[i][1][0].setGeometry(30, 50, 10, 20)

            self.scrollLayout.addRow(movies[i][1][0])