在 PyQT 中使用 Newstyle 信号传递参数
我在使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以使用
setattr
动态向对象添加属性You can add attribute dynamically to objects using
setattr
错误消息告诉您的是,您要替换
%s
的值之一的self.changeProject("%s")
返回None
。想必您的意思是让该方法返回不同的东西?当然,如果不查看代码,就不可能对进一步调试
changeProject
的任务提供太大帮助。但是,您可以将调用分成类似的内容(一旦您按照lazy1的建议摆脱了大量的执行人员):这样,您将看到所有名称,而不是无用地尝试“连接到无”在错误日志中导致令人惊讶的返回值,然后可以根据该信息继续调试。然而,更有可能的是,通过查看
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
returnsNone
. 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):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 fromchangeProject
(not from anotherconnect
!-) -- fixed the snippet accordingly.我认为你运行“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.
感谢您的帮助。我偶然发现了 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
QSignalMapper 是使用 Qt 完成此任务的公认方法,但我发现使用 PyQt 有点麻烦,因为有一些更简单的选项可用。最简单的可能是 1)用唯一的 id 标记每个按钮,以便您可以区分它们(或者仅使用按钮的文本),然后 2)使用 QObject.sender() 来确定哪个按钮发出信号。例如:
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:
我想对此进行详细说明,并提及我刚刚用来解决此策略的另一个策略/技巧。这是一个有些特定的策略,并不总是有效,但我选择为这种设置的最新实现将按钮设置为可检查。
这最终成为阻力最小的路径,因为我随后能够迭代布局并简单地检查哪个按钮对于 .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.