QMetaObject::invokeMethod 找不到带参数的方法 [英] QMetaObject::invokeMethod doesn't find methods with parameters

查看:184
本文介绍了QMetaObject::invokeMethod 找不到带参数的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是QMetaObject::invokeMethod没有找到方法的后续.调用没有参数的方法有效.但是将之前的问题扩展到带参数的方法让我再次失败.

This is a follow up of QMetaObject::invokeMethod doesn't find the method. Invoking a method without paramters works. But extending the previous question to methods with parameters brings me back to failure again.

请参阅以下 Python 示例脚本:

See the following example script in Python:

from PySide import QtCore

class Example(QtCore.QObject):
    def __init__(self):
        super().__init__()

    @QtCore.Slot()
    def dup(self):
        beep('dup-class')

    @QtCore.Slot(str)
    def beep(self, text):
        print(text)

@QtCore.Slot()
def dup(self):
    beep('dup-local')

@QtCore.Slot(str)
def beep(text):
    print(text)

if __name__ == '__main__':
    QtCore.QMetaObject.invokeMethod(None, 'dup')
    QtCore.QMetaObject.invokeMethod(None, 'beep', QtCore.Qt.AutoConnection, QtCore.QGenericArgument('text', 'beep-local'))

    print('now some classy trials')
    t = Example()
    QtCore.QMetaObject.invokeMethod(t, 'dup')
    QtCore.QMetaObject.invokeMethod(t, 'beep', QtCore.Qt.AutoConnection, QtCore.QGenericArgument('text', 'beep-class'))
    QtCore.QMetaObject.invokeMethod(t, 'beep', QtCore.Qt.AutoConnection, QtCore.QGenericArgument('self', t), QtCore.QGenericArgument('text', 'beep-class-b'))

PySide 1.2.1 和 Python 3.3 在 Windows 7 和 Ubuntu 14.04 上的输出也是:

The output with PySide 1.2.1 and Python 3.3 on Windows 7 and Ubuntu 14.04 as well is:

now some classy trials
dup-class
QMetaObject::invokeMethod: No such method Example::beep(text)
QMetaObject::invokeMethod: No such method Example::beep(self,text)

这意味着对本地方法的 invokeMethod 调用以静默方式失败.只有对 Example:dup() 的调用给出了预期的输出.使 Example:beep(str) 工作的两次试验都失败了,尽管失败消息给出了实际应该存在的方法签名.

This means that the invokeMethod calls to local methods failed silently. Only the call to Example:dup() gave the expected output. The two trials to get Example:beep(str) to work failed, although the failure messages give method signatures that actually should exist.

我在 PySide 上提出了这个问题的早期版本邮件列表,但没有得到答复.

I posed an earlier version of this question on the PySide mailing list but it wasn't answered.

问题:如何使 QMetaObject::invokeMethod 在 Python Qt 绑定(最好在 PySide)中使用参数调用本地和类方法?

Question: How to make QMetaObject::invokeMethod calling local and class method with parameters in the Python Qt bindings (preferably in PySide)?

顺便说一句:如果有人知道Signal:emit(...)QtCore.QTimer.singleShot(0, ...) 在下面做什么引擎盖,这也可以在这里提供帮助.毕竟,所有这些不同的方法都有非常相似的效果.

edit: By the way: if one knows what Signal:emit(...) or QtCore.QTimer.singleShot(0, ...) do under the hood, that could help here too. After all all these different approaches have very similar effects.

使用 'QString' 作为参数名称,警告消息消失,但 Python 整体失败并出现段错误.可能是 PySide 的一个实现错误.规则似乎是必须在 invokeMethod 中给出参数的 Qt-C++ 类型,在 Slots 中给出 Python 类型.

With 'QString' as parameter name the warning messages disappear but Python fails as a whole with segfaults. It may be an implementation bug of PySide. The rule seems to be that one has to give the Qt-C++ types of the parameters in invokeMethod and the Python types in the Slots.

from PySide import QtCore

class Example(QtCore.QObject):
    def __init__(self):
        super().__init__()

    @QtCore.Slot(str)
    def beep(self, text='default'):
        print(text)

if __name__ == '__main__':
    app = QtCore.QCoreApplication([])

    e = Example()
    QtCore.QMetaObject.invokeMethod(e, 'beep', QtCore.Qt.AutoConnection, QtCore.QGenericArgument('QString', 'beep'))

    QtCore.QTimer.singleShot(1000, app.quit)
    app.exec_()

推荐答案

对于仍然对此感兴趣的任何人:

For anybody still interested in this:

从 1.2.4 版本开始,PySide 有问题,因为它没有包装 Q_ARGQ_RETURN_ARG 宏.相反,它不明智地包装了 QGenericArgumentQGenericReturnArgument 类,它们是内部帮助类,并不打算直接实例化.因此,调用带参数的槽总是会导致分段错误.

As of version 1.2.4, PySide is buggy in that it doesn't wrap the Q_ARG and Q_RETURN_ARG macros. Instead, it unwisely wraps the QGenericArgument and QGenericReturnArgument classes, which are internal helper classes and not meant to be instanciated directly. As a result of this, invoking slots with arguments invariably results in a segmentation fault.

相比之下,PyQt 确实包装了宏而不是类,并且不会遇到同样的问题.

By comparison, PyQt does wrap the macros rather than the classes, and does not suffer from the same problems.

这篇关于QMetaObject::invokeMethod 找不到带参数的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆