So I am generating a menu of options based on some files on my system. I have a list list of objects I need to dynamically generate an option in the menu for and need to be able to let the function that is doing the creation know which object to use. After some research I found the post below. I could not comment as my rep is not high yet: How to pass arguments to callback functions in PyQt
When I run this the signal mapper is not working right. It is not even calling the handleButton correctly. Any ideas as to how to use the signal mapper correctly?
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.mapper = QtCore.QSignalMapper(self)
self.toolbar = self.addToolBar('Foo')
self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
for text in 'One Two Three'.split():
action = QtGui.QAction(text, self)
self.mapper.setMapping(action, text)
action.triggered.connect(self.mapper.map)
self.toolbar.addAction(action)
self.mapper.mapped['QString'].connect(self.handleButton)
self.edit = QtGui.QLineEdit(self)
self.setCentralWidget(self.edit)
def handleButton(self, identifier):
print 'run'
if identifier == 'One':
text = 'Do This'
print 'Do One'
elif identifier == 'Two':
text = 'Do That'
print 'Do Two'
elif identifier == 'Three':
print 'Do Three'
text = 'Do Other'
self.edit.setText(text)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.resize(300, 60)
window.show()
sys.exit(app.exec_())
EDIT:
I've found that by using old-style signal/slot connections this is fixed:
#action.triggered.connect(self.mapper.map)
self.connect(action, QtCore.SIGNAL("triggered()"), self.mapper, QtCore.SLOT("map()"))
and
#self.mapper.mapped['QString'].connect(self.handleButton)
self.connect(self.mapper, QtCore.SIGNAL("mapped(const QString &)"), self.handleButton)
Am I using the new-style connections incorrectly?
Based on this post as well as the original link I posted, I thought I was doing things correctly.
The original example code (which I wrote), works perfectly fine for me using either Python2 or Python3 with several different recent versions of PyQt4. However, if I use a really old version of PyQt4 (4.7), the handler no longer gets called.
The reason (and solution) for this is given in the response to the mailing list post you linked to:
There are some signals (like
clicked
andtriggered
) which always send a default value unless you explicitly request otherwise. With the old-style signals, you can specify the no default overload it withSIGNAL("triggered()")
, but with new-style signals, you have to do it like this:But that is only necessary with very old versions of PyQt4 - the underlying issue was fixed back in 2010 (don't know the exact version, but 4.8 should be okay).