在PyQT中使用Newstyle信号传递参数

时间:2010-09-27 20:48:42

标签: python pyqt signals

我在PyQT中使用一组动态创建的按钮时遇到了一些麻烦。

我正在使用列表来创建与不同值对应的按钮。因为每个按钮都不同,我需要让它们将参数传递给单独识别自己的“按钮单击”功能,这样我就可以用它们执行不同的操作。以下是我到目前为止的情况:

for x in self.buttons:
    name = str(x)
    button = QtGui.QPushButton(Frame)
    button.setText(name)
    cp_result = self.changeProject(name)
    if cp_result is None:
        print 'changeProject(%s) is None!', name
    else:
        print 'changeProject(%s) is OK (%r)', name, cp_result
        #button.clicked.connect(cp_result)
    setattr(self, "btn_%s" % name, button)
    self.btnList.append(button)

def changeProject(self, name):
    for x in self.btnList:
        if x.isDown:
            #Change UI Frame to blahblah
    return 'A String'

使用Alex,这是最新的代码,在changeProject上测试一个返回值,它显然不能是一个字符串,但我仍然需要确定在自动生成的按钮之间按下了哪个按钮。

当前错误:TypeError: connect() slot argument should be a callable or a signal, not 'str'

6 个答案:

答案 0 :(得分:1)

您可以使用setattr

动态地向对象添加属性
for x in buttons:
    name = str(x)
    button = QtGui.QPushButton(Frame)
    button.setText(name)
    button.clicked.connect(self.changeProject(name))
    setattr(self, "btn_%s" % name, button)

答案 1 :(得分:1)

错误消息告诉您的是self.changeProject("%s"),其中一个值代替%s None返回changeProject。大概你是想让那种方法返回不同的东西?

当然,在没有看到代码的情况下,进一步调试cp_result = self.changeProject(name) if cp_result is None: logging.error('changeProject(%s) is None!', name) else: logging.info('changeProject(%s) is OK (%r)', name, cp_result) button.clicked.connect(cp_result) 的任务是不可能的。但是,您可以将调用拆分成类似的东西(根据lazy1的建议,你已经摆脱了大量的高管):

changeProject

通过这种方式而不是无用地尝试“连接到无”,您将看到所有名称在您的错误日志中导致令人惊讶的返回值,然后可以根据该信息继续调试。但是,更有可能的是,通过查看connect的来源,您的错误实际上可能变得明显。

修改changeProject的参数当然来自connect(而不是来自其他{{1}}! - ) - 相应地修复了代码段。< / p>

答案 2 :(得分:0)

我认为你运行'exec'太多了,IMO。您的问题是您正在尝试连接到QPushButton的.clicked(),这实际上是一个信号。你真的需要在这里传递论点吗?

exec 'self.btn_%s.clicked.connect(self.changeProject("%s"))' % (x, x)

因为如果不这样做,你可以这样连接:

self.connect(self.btn_%s, SIGNAL('clicked()'), self.changeProject)

如果您需要知道单击了哪个按钮,可以遍历列表以查找单击的按钮:

for x in buttons:
if x.isDown(): (function)


您也可以使用pyqtSignal。

答案 3 :(得分:0)

感谢您的帮助。我偶然发现了QSignalMapper,结果证明这正是我所需要的。

http://pysnippet.blogspot.com/2010/06/qsignalmapper-at-your-service.html

答案 4 :(得分:0)

QSignalMapper是使用Qt实现这一目标的可接受方式,但我发现PyQt有点麻烦,因为有一些更简单的选项可用。最简单的可能是1)用唯一的id标记每个按钮,这样你就可以区分它们(或者只是使用按钮的文本),然后2)使用QObject.sender()来确定发出信号的按钮。例如:

for x in self.buttons:
    name = str(x)
    button = QtGui.QPushButton(Frame)
    button.setText(name)
    button.uniqueId = name  ## make this whatever you want..
    button.clicked.connect(buttonClicked)

def buttonClicked():
    button = QObject.sender()
    uid = button.uniqueId  ## got your ID back

答案 5 :(得分:0)

我想暗示这一点,并提到我刚刚用来解决这个策略的另一个策略/黑客。这是一个有点特定的策略并不总是有效,但我选择为更近期的这种设置实现的操作是将按钮设置为可检查。

由于我当时能够遍历布局并简单地检查哪个按钮为.isChecked(),因此最终阻力最小。无需SignalMapping或额外属性。