Skip to content Skip to sidebar Skip to footer

Passing Arguments With Newstyle Signals In Pyqt

I've been having some trouble with a set of dynamically created buttons in PyQT. I'm using a list to create buttons corresponding to different values. Because each button is diffe

Solution 1:

You can add attribute dynamically to objects using setattr

for x in buttons:
    name = str(x)
    button = QtGui.QPushButton(Frame)
    button.setText(name)
    button.clicked.connect(self.changeProject(name))
    setattr(self, "btn_%s" % name, button)

Solution 2:

What the error message is telling you is that self.changeProject("%s") for one of the values you're substituting for that %s returns None. Presumably you meant for that method to return something different?

It's impossible to help you much with the task of debugging changeProject further without seeing the code for it, of course. However, you could for example split the call into something like (once you've gotten rid of that ton of execs as per lazy1's suggestion):

cp_result = self.changeProject(name)
if cp_result isNone:
    logging.error('changeProject(%s) is None!', name)
else:
    logging.info('changeProject(%s) is OK (%r)', name, cp_result)
    button.clicked.connect(cp_result)

This way instead of uselessly trying to "connect to None", you'll see all the names causing that to-you-surprising return value in your error log, and can then continue debugging based on that information. However, more likely than not, your bug might in fact become obvious by looking at the source of changeProject.

Edit: the argument to connect is of course coming from changeProject (not from another connect!-) -- fixed the snippet accordingly.

Solution 3:

Thanks for the assistance. I stumbled QSignalMapper, and this turned out to be exactly what I needed.

http://pysnippet.blogspot.com/2010/06/qsignalmapper-at-your-service.html

Solution 4:

QSignalMapper is the accepted way to accomplish this with Qt, but I have found it to be somewhat cumbersome with PyQt since there are some simpler options available. The easiest is probably to 1) tag each button with a unique id so you can tell them apart (or just use the button's text), then 2) use QObject.sender() to determine which button emitted the signal. For example:

for x in self.buttons:
    name = str(x)
    button = QtGui.QPushButton(Frame)
    button.setText(name)
    button.uniqueId = name  ## make this whatever you want..
    button.clicked.connect(buttonClicked)

def buttonClicked():
    button = QObject.sender()
    uid = button.uniqueId  ## got your ID back

Solution 5:

I'd like to necro this and mention another strategy/hack I just employed to solve this strategy. This is a somewhat specific strategy that wouldn't always work, but what I opted to do for a more recent implementation of this kind of setup was set the buttons as checkable.

This wound up being the path of least-resistance since I was then able to iterate through the layout and simply check which button held true for .isChecked(). No SignalMapping or extra attributes necessary.

Post a Comment for "Passing Arguments With Newstyle Signals In Pyqt"