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

发布于 2024-09-25 03:23:40 字数 872 浏览 4 评论 0原文

我在使用 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() 槽参数应该是可调用或信号,而不是“str”

I've been having some trouble with a set of dynamically created buttons in PyQT.

I'm using a list to create buttons corresponding to different values. Because each button is different, I need to have them pass an argument to the "Button Clicked" function identifying themselves separately so I can perform different actions with them. Here is what I have so far:

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'

Working with Alex, this is the latest code, testing a return value on changeProject, which clearly cannot be a string, but I still need to determine which button is pressed between the auto-generated buttons.

Current error: TypeError: connect() slot argument should be a callable or a signal, not 'str'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

够运 2024-10-02 03:23:40

您可以使用 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)

You can add attribute dynamically to objects using 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)
不语却知心 2024-10-02 03:23:40

错误消息告诉您的是,您要替换 %s 的值之一的 self.changeProject("%s") 返回 None。想必您的意思是让该方法返回不同的东西?

当然,如果不查看代码,就不可能对进一步调试 changeProject 的任务提供太大帮助。但是,您可以将调用分成类似的内容(一旦您按照lazy1的建议摆脱了大量的执行人员):

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)

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

编辑connect的参数当然来自changeProject(而不是来自另一个connect!-)--相应地修复了片段。

What the error message is telling you is that self.changeProject("%s") for one of the values you're substituting for that %s returns None. Presumably you meant for that method to return something different?

It's impossible to help you much with the task of debugging changeProject further without seeing the code for it, of course. However, you could for example split the call into something like (once you've gotten rid of that ton of execs as per lazy1's suggestion):

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)

This way instead of uselessly trying to "connect to None", you'll see all the names causing that to-you-surprising return value in your error log, and can then continue debugging based on that information. However, more likely than not, your bug might in fact become obvious by looking at the source of changeProject.

Edit: the argument to connect is of course coming from changeProject (not from another connect!-) -- fixed the snippet accordingly.

忆悲凉 2024-10-02 03:23:40

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

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

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

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

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

按钮中的 x:
if x.isDown(): (函数)

您还可以使用 pyqtSignal。

I think you running 'exec' is too much, IMO. Your problem is that you are trying to connect to the QPushButton's .clicked(), which is really a signal. Do you really need to pass the argument here

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

Because if you don't you can connect it like this:

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

If you need to know which button is clicked you can iterate through the list to find which button is clicked:

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

You can also use pyqtSignal.

聆听风音 2024-10-02 03:23:40

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

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

Thanks for the assistance. I stumbled QSignalMapper, and this turned out to be exactly what I needed.

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

平生欢 2024-10-02 03:23:40

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

QSignalMapper is the accepted way to accomplish this with Qt, but I have found it to be somewhat cumbersome with PyQt since there are some simpler options available. The easiest is probably to 1) tag each button with a unique id so you can tell them apart (or just use the button's text), then 2) use QObject.sender() to determine which button emitted the signal. For example:

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
世界和平 2024-10-02 03:23:40

我想对此进行详细说明,并提及我刚刚用来解决此策略的另一个策略/技巧。这是一个有些特定的策略,并不总是有效,但我选择为这种设置的最新实现将按钮设置为可检查。

这最终成为阻力最小的路径,因为我随后能够迭代布局并简单地检查哪个按钮对于 .isChecked() 来说是正确的。不需要 SignalMapping 或额外的属性。

I'd like to necro this and mention another strategy/hack I just employed to solve this strategy. This is a somewhat specific strategy that wouldn't always work, but what I opted to do for a more recent implementation of this kind of setup was set the buttons as checkable.

This wound up being the path of least-resistance since I was then able to iterate through the layout and simply check which button held true for .isChecked(). No SignalMapping or extra attributes necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文