在PyQ中将列表元素作为signal/slot参数传递

2024-04-18 18:48:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我想把调用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)

所以,如您所见,我试图传递list element自身字段列表[i] 作为checkState()函数中名为line的参数。如果我显式定义字段列表元素(即自身字段列表[0])在checkState()函数中,代码运行得很好,但我不能将其作为参数传递。我做错什么了?在

顺便说一句,编译器在我尝试运行程序时不会给我错误消息,但它根本无法完成它应该做的工作(当我写超过3个字符时,请更改QLineEdit的颜色)

编辑:

@dex19dt

是的,这是一个例子,但你是对的!只有最后一个QLineEdit才能正常工作!在

问题是,我不能给出所有这些小部件的名称,因为它们的数量取决于所选的层,这意味着有时有5个小部件,有时甚至有11个或75个。在

我可以很容易地命名这些小部件并将文本设置为:

^{pr2}$

这对每个小部件都很好,但我不知道如何定义信号?你有什么主意吗?在


编辑:

@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定义为新变量。。。试着用谷歌搜索,但没有成功。在


Tags: 对象lambda函数self列表定义部件connect
1条回答
网友
1楼 · 发布于 2024-04-18 18:48:24

好吧,我假设你问题中的代码是一个例子,而不是你真正的代码。因为,由于您是在一个没有附加参数的循环中创建小部件,结果将是窗口中所有对象的重叠。你看,所有的线编辑都在同一个地方(默认情况下,窗口的左上角)。如果是这样的话,很难判断问题出在哪里,因为在我看来,这只是知道lineEdit的哪个实例正在发送信号的问题。在

所以我会告诉你如何让上面的代码工作,如果不是这样,你可以随时回复。在

一切都与信号的连接方式有关。如果查看代码,则创建的所有行编辑都具有相同的名称(自身值字段). 这些对象都是创建的,它们在内存中有自己的位置,但是它们在connect中的引用总是被最后一个connect覆盖。你甚至可以做测试。如果将此行添加到checkState函数:

print self.fieldList.index(line)

您将看到,该信号总是针对列表的最后一项调用的,这也是连接的最后一个信号。在

只需使用不同的名称逐个设置所有线条编辑即可。创建你的列表,同时输入所有的名字。这样,for循环将只连接线编辑,而不再创建它们。在

编辑:

好吧。其中一种方法是使用信号映射器。 看看docs here。在

在上面的示例中,您可以执行以下操作:

首先声明映射器,与声明其他小部件的方法相同:

self.myMapper = QtCore.QSignalMapper()

在你的第一个for循环之后。迭代列表:

^{pr2}$

因此,它将映射列表中的每个对象及其在列表(int)上对应的索引。 因此,当发出一个信号时,映射器使用该索引值作为参数调用checkState函数。这样,您就可以再次使用列表访问对象:

def checkState(i):
    print (self.fieldList[i].objectName())
    self.fieldList[i].setText("It works!")

如您所见,映射器只将索引作为参数发送。所以我想您需要使用额外的参数palette1, palette2来调整函数。 或者,您可以使用一个preliminar函数(如过滤器),然后在其中调用正确的checkState函数:

def myfilter(i):
    checkState(self.fieldList[i], palette1, palette2)

我很确定还有其他的方法可以让这项工作成功,但这项工作做得很好,而没有更好的解决方案出现。在

相关问题 更多 >