Qtcore.Qobject.Connect in a Loop Only Affects the Last Instance

QtCore.QObject.connect in a loop only affects the last instance

I have same problem , you should use functools.partial such as:

for key, val in a_DICT_THAT_YOU_STORED_YOUR_OBJECTS_AND_STRINGS:
obj = partial( findInstance.projectsInstance.myslot,arg1="TWCH",arg2=self,arg3=key,arg4=val.checkState() )
QtCore.QObject.connect(val, QtCore.SIGNAL(_fromUtf8("stateChanged (int)")), obj)

Of course, argX should set to your real name of your argument of your function name.

PyQt connect inside for loop vs. separate calls results in different behavior

When you connect a signal to a lambda function, the contents of the lambda function are evaluated when the signal is emitted, not when the signal is connected. As such, the variables you use (marker_one and marker_two) always point to the objects created in the last iteration of the loop.

One simple solution is to explicitly pass in marker_one and marker_two as default arguments to variables of the same name, in the signature of the lambda function:

lambda marker_one=marker_one: self.update_marker_vals(marker_one, "Marker One")
lambda marker_two=marker_two: self.update_marker_vals(marker_two, "Marker Two")

There are several useful answers relating to a very similar problem here, specifically the answer by ekhumoro, if you would like to know more (my answer to that question my also be of use, although ekhumoro's solution is cleaner)

how to pass a dynamic generated QPushButton to a SIGNAL handler function in python?

The problem was that the value of d['id'] wasn't being evaluated until after the loop had completed, so while all the buttons were being connected, only the last id was being sent. You need to ensure that the id value is evaluated during the loop.

You can use functools.partial to do this

from functools import partial

for d in chosen:
itembtn = QPushButton("ID : "+str(d['id']))
itembtn.clicked.connect(partial(self.handlerFunction, str(d['id'])))
self.layoutbottom.addWidget(itembtn)

PyQt4: Signal slot mechanism doesn't work correctly for 'List of buttons'

You need to bind the value for each created (lambda) function. To do that, you can pass them as parameter with a default value:

for i in range(6):
self.btn[i].clicked.connect(lambda i=i: self.btnAction(i))

Here is a minimal example to show the effect:

def test_function(x):
return x


def test():
# DO NOT USE THIS. This is just for showing the effect
wrong = list()
for i in range(6):
wrong.append(lambda: test_function(i))

for w in wrong:
print(w()) # will always print 5

print("-"*10)
# This is the desired behaviour
right = list()
for i in range(6):
right.append(lambda i=i: test_function(i))

for r in right:
print(r())

if __name__ == '__main__':
test()

Which gives the following output:

5
5
5
5
5
5
----------
0
1
2
3
4
5

Alternatively you can use partial from the functools package:

for i in range(6):
self.btn[i].clicked.connect(partial(self.btnAction, i))

Creating PyQt5 buttons in a loop: all buttons trigger the same callback

I do not understand what type of structure is matrix, but I think it is equivalent to a list of dictionaries.

The problem is that you must pass as an argument to the lambda function assigning it, the clicked signal takes as a parameter a Boolean value that indicates that if the button is checked or not (by default this property is disabled so that this value is false), you must add another parameter.

class App(QMainWindow):
def launch(self, filepath):
subprocess.run(filepath)

def __init__(self):
super(App, self).__init__()

matrix = [{"path": "path1", "setIcon": "icon1", "posx": 0, "posy": 0},
{"path": "path2", "setIcon": "icon2", "posx": 0, "posy": 150},
{"path": "path3", "setIcon": "icon3", "posx": 0, "posy": 300}]

for value in matrix:

filepath = value['path']
icon = value['setIcon']
posx = value['posx']
posy = value['posy']

btn = QToolButton(self)
btn.setIcon(QIcon(icon))
btn.setIconSize(QSize(64, 64))
btn.resize(100, 100)
btn.move(posx, posy)
btn.clicked.connect(lambda checked, arg=filepath: self.launch(arg))

self.initUI()

def initUI(self):
self.setGeometry(150, 150, 1250, 650)
self.setWindowTitle('LinuxLauncher')
self.show()

Passing argument to PyQt SIGNAL connection

Here is a different approach: instead of attaching the data as an argument to the signal handler, attach it to the menu-item itself. This offers much greater flexibility, because the data is not hidden inside an anonymous function, and so can be accessed by any part of the application.

It is very easy to implement, because Qt already provides the necessary APIs. Here is what your example code would look like if you took this approach:

        for j in range(0, len(self.InputList)):

arrow = QtGui.QPushButton(self)
arrow.setGeometry(QtCore.QRect(350, 40*(j+3)+15, 19, 23))

menu = QtGui.QMenu(self)
group = QtGui.QActionGroup(menu)
for element in SomeList:
action = menu.addAction(element)
action.setCheckable(True)
action.setActionGroup(group)
action.setData(j)
arrow.setMenu(menu)

group.triggered.connect(self.SomeFunction)

def SomeFunction(self, action):
print(action.data())

PySide - QStackedLayout.setCurrentIndex() does not work as expected when it's inside a for-loop

See this question. It's a different question, but they're having essentially the same problem. This line is the issue

self.type_top_button.clicked.connect(lambda: stack_layout.setCurrentIndex(i))

Specifically

lambda: stack_layout.setCurrentIndex(i)

The problem is that the value of i is not evaluated when you create the lambda function. It's evaluated when the lambda function is called, and by that point, the loop has finished and every lambda will be using the exact same value of i at the end of the loop, not the value of i when the lambda was created.

You can fix this two ways. The first is to use default arguments in your lambda, which forces the value of i to be evaluated at function creation time.

lambda i=i: stack_layout.setCurrentIndex(i) 

Alternatively, you can use functools.partial

from functools import partial

self.type_top_button.clicked.connect(partial(layout.setCurrentIndex, i))


Related Topics



Leave a reply



Submit