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.
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'))
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)
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.
I posed an earlier version of this question on the PySide mailing list but it wasn't answered.
Question: How to make QMetaObject::invokeMethod
calling local and class method with parameters in the Python Qt bindings (preferably in PySide)?
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.
edit2:
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_()
See Question&Answers more detail:
os