Qt:slot 返回值的含义?

27
根据文档,插槽的返回值没有任何意义。但是在生成的 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;
5个回答

19

如果您想将槽函数作为普通成员函数调用,返回值才有用:

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方法可以用于调用槽并获取返回值。虽然这似乎稍微复杂了一些。


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;

_a向量是传递给qt_metacall的参数列表。这是通过QMetaObject :: invokeMethod传递的。因此,在由moc生成的代码中保存了返回值,并传回给调用者。因此,对于正常的信号槽交互,返回值根本没有用处。但是,该机制存在是为了让插槽的返回值在通过invokeMethod调用插槽时可以被访问。


7

当您处理qtscript JavaScript QtPython等动态语言时,它非常有用。使用此语言/绑定,您可以使用由MetaObject提供的接口动态地使用C++ QObject。正如您可能知道的那样,仅信号和插槽由moc解析并生成MetaObject描述。因此,如果您从javascript绑定中使用C++ QObject,您将能够调用仅插槽,并且您将需要返回值。通常,用于动态语言的Qt绑定提供了一些访问普通方法的工具,但该过程肯定更加棘手。


1
看一下 QWebFrame::addToJavaScriptWindowObject,并思考如何让该框架中的 javascript 从您添加的对象获取数据。 - FxIII

5

所有的槽函数都在QMetaObject中公开,通过反射接口可以访问对象。

例如,QMetaObject::invokeMethod()接受一个QGenericReturnArgument参数。因此我认为这不是用于显式槽函数的使用,而是用于一般方法的动态调用。(有其他方法可以将方法公开给QMetaObject而不是将其转换为槽函数。)

例如,各种动态语言(如QML和Javascript)使用invokeMethod函数来调用QObject的方法。(还有一个名为PythonQt的Python-Qt桥,它也使用了这个功能。请不要与完整的PyQt包装器PyQt混淆。)

当在Qt应用程序内进行同步跨线程调用时(通过使用invokeMethod并将连接类型设置为Qt::BlockingQueuedConnection),返回值会被使用。该连接类型有以下文档:

与QueuedConnection相同,除了当前线程会阻塞直到槽函数返回。 此连接类型仅应在发射器和接收器位于不同线程的情况下使用。注意:违反此规则可能会导致应用程序死锁。


0

这个问题最初是在14年前提出的。现在QML允许Slots返回一个值,这是确定的。

您必须使用result参数声明返回值的类型(请注意,它不是return而是result)。

在Python中,将两个数字传递给Slot并接受一个值,语法将是

@pyqtSlot(int, int, result=int)
def add(x,y):
    return x + y

你可以称之为:
ret_val = add(1, 2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接