gpt4 book ai didi

python - 在 PyQt 中将列表元素作为信号/槽参数传递

转载 作者:太空宇宙 更新时间:2023-11-03 19:16:43 25 4
gpt4 key购买 nike

我想传递调用信号的对象作为函数的参数,这样我就可以在该函数中操作该对象。该对象是 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] 作为名称为 line 的参数传递到 checkState( ) 函数。如果我在 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)))

这样当前索引就会复制到信号索引。虽然我不太确定为什么会有旧的,新的部分。它是引用 lambda 函数还是简单地将左 i 定义为旧变量,将右 i 定义为新变量...尝试用谷歌搜索它,但没有成功。

最佳答案

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

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

这一切都与信号的连接方式有关。如果您查看代码,就会发现您正在创建具有相同名称(self.valueField)的所有行编辑。这些对象都已创建,并且它们在内存中拥有自己的位置,但它们在连接中的引用始终会被最后一个连接覆盖。您甚至可以进行测试。如果将此行添加到 checkState 函数中:

打印 self.fieldList.index(line)

您将看到始终为列表的最后一项调用信号,这也是最后连接的信号。

您可以简单地用不同的名称一一设置所有行编辑。创建您的列表并在其中输入所有名称。这样你的 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)

我很确定存在其他方法来完成这项工作,但是这个方法可以完成这项工作,但没有出现更好的解决方案。

关于python - 在 PyQt 中将列表元素作为信号/槽参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11117052/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com