QMetaObject::invokeMethod 找不到方法

2 投票
1 回答
3977 浏览
提问于 2025-04-18 03:05

我想用 QMetaObject::invokeMethod 来调用一个对象的方法(以后这个方法会在另一个线程中运行,这时候 invokeMethod 就很有用了)。我在 Python 3.3 上使用的是 Qt 4.8 的 PySide 1.2.1 版本。完整的例子是:

from PySide import QtCore

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

    def beep(self):
        print('beep')

if __name__ == '__main__':
    t = Tester()
    QtCore.QMetaObject.invokeMethod(t, 'beep', QtCore.Qt.AutoConnection)

而输出是:

QMetaObject::invokeMethod: No such method Tester::beep()

我本来期待的是 beep。但是这个方法并没有被调用。

那到底哪里出问题了呢?看起来这么简单,我却找不到错误。


补充:我通过在方法上加上 `@QtCore.Slot` 装饰器让它工作了。感谢评论和回答。

1 个回答

4

你不能调用普通的方法,只能使用信号和槽。这就是为什么你遇到问题的原因。想了解更多,可以查看QMetaObject的文档

这个方法会在对象obj上调用某个成员(信号或槽的名字)。如果成功调用了这个成员,就返回true。如果没有这个成员或者参数不匹配,就返回false。

试试这个装饰器:

...
@QtCore.Slot()
def beep(self):
    print('beep')
...

想了解更多,可以查看以下文档,还有这个文档

使用QtCore.Slot()

槽是通过装饰器QtCore.Slot()来定义和重载的。要定义一个签名,只需像使用QtCore.Signal()类那样传递类型。与Signal()类不同的是,重载一个函数时,你不需要把每种变化都作为元组或列表传递。相反,你需要为每种不同的签名定义一个新的装饰器。下面的示例部分会让这一点更清楚。

另一个不同之处在于它的关键字。Slot()接受一个名字和一个结果。结果关键字定义了返回的类型,可以是C语言类型或Python类型。name的行为和Signal()中的一样。如果没有传递名字,那么新的槽将和被装饰的函数同名。

撰写回答