我想传递调用signal的对象,作为函数的参数,以便我可以在该函数中使用该对象进行操作。该对象是QLineEdit小部件。这是一个例子:
self.fieldList = []
for i in range(10):
self.valueField = QtGui.QLineEdit()
self.fieldList.append(self.valueField)
self.fieldList[i].cursorPositionChanged.connect(lambda: (self.checkState(self.fieldList[i], palette1, palette2)))
def checkState(self, line, palette1, palette2):
if len(line.text()) > 3:
line.setPalette(palette1)
else:
line.setPalette(palette2)
因此,正如您所看到的,我正在尝试将列表元素 self.fieldList [i] 作为参数传递给 checkState中名为 line 的参数( )功能。如果我在 checkState()函数中明确定义了 fieldList 元素(即 self.fieldList [0] ),那么代码运行完美,但是我不能传递它作为参数。我做错了什么?
顺便说一下。当我尝试运行程序时编译器没有给我错误消息,但它根本不会完成应该的工作(当我写3个以上的字符时改变QLineEdit的颜色)
修改
@ dex19dt
是的,这是一个例子,但你是对的!只有最后一个QLineEdit才能正常工作!
问题是,我不能给所有这些小部件名称,因为它们的数量取决于所选的图层,这意味着有时会有5个小部件,有时甚至是11或75个小部件。
我可以轻松地命名这些小部件并设置文本:
self.fieldList[i].setObjectName(_fromUtf8("attributeValueField_{0}".format(i)))
self.fieldList[i].setText(_fromUtf8("{0}".format(value.toString())))
这适用于每个小部件,但我不知道如何定义信号?你有什么想法吗?
修改
@ dex19dt
好的,所以我问这个索引问题没有“坚持”到函数调用,我发现这只是python的工作方式,并且要修复这个问题我需要替换这一行:
self.fieldList[i].cursorPositionChanged.connect(lambda: (self.checkState(self.fieldList[i], palette1, palette2)))
这一个:
self.fieldList[i].cursorPositionChanged.connect(lambda old, new, i=i: (self.checkState(self.fieldList[i], palette1, palette2)))
所以这样当前索引复制到信号索引。虽然我不确定为什么会有old, new
部分。它是指lambda函数还是简单地将左i
定义为旧i
作为新变量...尝试使用Google搜索,但没有成功。
答案 0 :(得分:1)
好吧,我假设您的问题中的代码是一个示例,而不是您的真实代码。因为,您在循环中创建小部件而没有其他参数,结果将是窗口中所有对象的重叠。你看,所有lineEdits都在同一个地方(默认情况下,窗口的左上角部分)。如果是这种情况,将很难分辨问题在哪里,因为在我看来,这只是知道lineEdit的哪个实例正在发送信号。
因此,我将告诉您如何使代码在上面工作,如果不是这样,您可以随时回复。
关于信号连接的方式。如果您查看代码,则会创建具有相同名称的所有lineEdits(self.valueField)。这些对象都已创建,并且它们在内存中有自己的位置,但它们在连接中的引用始终被最后一次连接覆盖。你甚至可以进行测试。如果将此行添加到checkState函数:
print self.fieldList.index(line)
您将看到始终为列表的最后一项调用信号,这也是最后连接的信号。
您可以使用不同的名称逐个设置所有lineEdits。并创建您的列表,同时键入其中的所有名称。这样你的for循环只会连接lineEdits而不再创建它们。
编辑:
确定。使这项工作的一种方法是使用SignalMapper。 看看docs here。
在上面的示例中,您可以执行以下操作:
首先声明映射器,就像声明其他小部件一样:
self.myMapper = QtCore.QSignalMapper()
在你的第一个for循环之后。你遍历列表:
for item in self.fieldList:
self.myMapper.setMapping(item, self.fieldList.index(item))
item.textEdited.connect(self.myMapper.map)
self.myMapper.mapped[int].connect(checkState)
那么这将做的是它将映射列表中的每个对象与列表(int)上的相应索引。 因此,当发出信号时,映射器将该索引值作为参数调用checkState函数。这样,您可以再次使用列表访问对象:
def checkState(i):
print (self.fieldList[i].objectName())
self.fieldList[i].setText("It works!")
如您所见,映射器仅将索引作为参数发送。所以我想你需要使用额外的参数palette1, palette2
来调整你的函数。
或者您可以使用类似过滤器的预备函数,然后在其中调用正确的checkState函数:
def myfilter(i):
checkState(self.fieldList[i], palette1, palette2)
我很确定存在其他方法可以使这项工作,但是这个方法可以完成工作,而更好的解决方案却没有显示出来。