根据文档,插槽的返回值并不意味着什么 然而在生成的moc代码中,我看到如果一个槽返回一个值,则该值用于某些东西。知道它做了什么吗?
这是我正在谈论的一个例子。这是从moc生成的代码中获取的。 'message'是一个不返回任何内容的插槽,'selectPart'被声明为返回int。
case 7: message((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
case 8: { int _r = selectPart((*reinterpret_cast< AppObject*(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])));
if (_a[0]) *reinterpret_cast< int*>(_a[0]) = _r; } break;
答案 0 :(得分:12)
通过Qt源看来,当从QMetaObject :: invokeMethod调用一个槽时,可以指定返回类型并获得返回值。 (看看Qt帮助中的invokeMethod)
我找不到很多在Qt源中实际使用的例子。我找到的是
bool QAbstractItemDelegate::helpEvent
这是一个带有返回类型的插槽,从
调用QAbstractItemView::viewportEvent
使用invokeMethod。
我认为插槽的返回值仅在直接调用函数时(当它是普通的C ++函数时)或使用invokeMethod时才可用。我认为这实际上是用于内部Qt功能,而不是在使用Qt的程序中正常使用。
编辑: 对于示例案例:
case 8: { int _r = selectPart((*reinterpret_cast< AppObject*(*)>(_a[1])), *reinterpret_cast< int(*)>(_a[2])));
if (_a[0]) *reinterpret_cast< int*>(_a[0]) = _r; } break;
vector _a是传递给qt_metacall的参数列表。这是由QMetaObject :: invokeMethod传递的。因此,moc生成的代码中的返回值被保存并传递回调用者。因此,对于正常的信号槽交互,返回值根本不用于任何事物。但是,该机制存在,因此如果通过invokeMethod调用插槽,则可以访问插槽的返回值。
答案 1 :(得分:12)
仅当您要将插槽作为普通成员函数调用时,返回值才有用:
class MyClass : public QObject {
Q_OBJECT
public:
MyClass(QObject* parent);
void Something();
public Q_SLOTS:
int Other();
};
void MyClass::Something() {
int res = this->Other();
...
}
编辑:似乎这不是返回值的唯一使用方式,QMetaObject :: invokeMethod方法可用于调用插槽并获取返回值。虽然看起来这样做有点复杂。
答案 2 :(得分:6)
在处理qtscript JavaScript QtPython等动态语言时非常有用。使用这种语言/绑定,您可以使用MetaObject提供的接口使用C ++ QObject。您可能知道,只有信号和插槽由moc解析并生成MetaObject描述。因此,如果您使用来自javascript绑定的C ++ QObject,您将只能调用插槽,并且您将需要返回值。通常,动态语言的Qt绑定提供了一些访问普通方法的工具,但这个过程肯定更加模糊。
答案 3 :(得分:4)
所有插槽都在QMetaObject中公开,可以通过反射接口访问对象。
例如,QMetaObject::invokeMethod()采用QGenericReturnArgument
参数。所以我相信这不是用于显式插槽使用,而是用于一般的方法的动态调用。 (还有其他方法可以将方法公开给QMetaObject,而不是将它们放入插槽中。)
例如,invokeMethod
函数被各种动态语言(如QML和Javascript)用于调用QObject:s
的方法。 (还有一个名为PythonQt的Python-Qt桥使用它。不要与PyQt混淆,后者是一个完整的包装器。)
在Qt应用程序内的线程之间进行同步调用时使用返回值(通过invokeMethod支持并将连接类型设置为Qt::BlockingQueuedConnection
,其中包含以下文档:
与QueuedConnection相同,但当前线程阻塞直到 槽返回。 此连接类型仅应用于发射器和接收器的位置 在... 不同的线程。注意:违反此规则可能会导致您的应用程序 陷入僵局。