PyQT Connecting lambda function to Signal

匿名 (未验证) 提交于 2019-12-03 01:20:02

问题:

I'm stuck with the following problem. I'm trying to connect a lambda function to a Signal for passing some extra data eventually.

def createTimeComboBox(self,slotCopy):     timeComboBox = QComboBox()      #...      cmd = lambda func=self.test:func()     self.connect(timeComboBox, SIGNAL("currentIndexChanged(int)"),cmd)  #...  def test(self, value):     print value 

When I run createTimeComboBox(), I get this error:

TypeError: 'int' object is not callable 

Changing

self.connect(timeComboBox, SIGNAL("currentIndexChanged(int)"),cmd) 

to

self.connect(timeComboBox, SIGNAL("currentIndexChanged(int)"),self.test) 

works fine, but I would like to be able to pass the slotCopy variable as well, so assumed that I need to use the lambda approach.

I had done this previously with a QPushButton's clicked() signal and that worked fine.

def createToDoctorButton(self,extraData):     toDoctorButton = QPushButton()      cmd = lambda func=self.goToDoctor:func(extraData)     self.connect(toDoctorButton,  SIGNAL('clicked()'),cmd)      return toDoctorButton  def goToDoctor(self,extraData):     print extraData 

I hope this makes sense - does anyone have any ideas? Thanks for any suggestions! Cheers Dave

回答1:

Your lambda accepts a parameter (func):

lambda func=self.test:func()  

Although the parameter has a default, it will be replaced if a parameter is passed. Looking at the signal, currentIndexChanged(int), shows that the signal will pass an integer parameter. func will be the integer coming from currentIndexChanged. Later, doing func() will be effectively trying to call an integer object which obviously is not legal (as the error indicates)

You need another parameter in your lambda to "catch" the passed parameter without overriding the func parameter:

cmd = lambda value, func=self.test: func(value) 

By the way, your test method expects a parameter, so you can't just do func().

You didn't have that problem with the clicked() signal because it doesn't pass a parameter to replace the default value.



回答2:

See if this works for you:

timeComboBox.currentIndexChanged.connect(self.test) 

Here is a small working example, demonstrating new style signals/slots connection with and without lambdas:

#!/usr/bin/env python #-*- coding:utf-8 -*-  from PyQt4 import QtCore, QtGui  class myWindow(QtGui.QWidget):     def __init__(self, parent=None):         super(myWindow, self).__init__(parent)          self.comboBox = QtGui.QComboBox(self)         self.comboBox.addItems([str(x) for x in range(3)])         self.comboBox.currentIndexChanged.connect(self.on_comboBox_currentIndexChanged)          slotLambda = lambda: self.on_comboBox_currentIndexChanged_lambda("some_value")         self.comboBox.currentIndexChanged.connect(slotLambda)      @QtCore.pyqtSlot(int)     def on_comboBox_currentIndexChanged(self, value):         print value      @QtCore.pyqtSlot(str)     def on_comboBox_currentIndexChanged_lambda(self, string):         print string  if __name__ == "__main__":     import sys      app = QtGui.QApplication(sys.argv)     app.setApplicationName('myWindow')      main = myWindow()     main.show()      sys.exit(app.exec_()) 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!