Qt信号可以返回一个值吗?

Boost.Signals允许使用槽的返回值形成信号的返回值的各种策略 。 例如添加它们,形成一个vector ,或返回最后一个。

Qt文档[编辑:以及这个问题的一些答案]中expression的共同的智慧是Qt信号不可能有这样的事情。

但是,当我在以下类定义上运行moc时:

 class Object : public QObject { Q_OBJECT public: explicit Object( QObject * parent=0 ) : QObject( parent ) {} public Q_SLOTS: void voidSlot(); int intSlot(); Q_SIGNALS: void voidSignal(); int intSignal(); }; 

moc不仅不抱怨非void返回types的信号,它似乎积极地实现它,以便允许返回值通过:

 // SIGNAL 1 int Object::intSignal() { int _t0; void *_a[] = { const_cast<void*>(reinterpret_cast<const void*>(&_t0)) }; QMetaObject::activate(this, &staticMetaObject, 1, _a); return _t0; } 

所以:根据文件,这件事是不可能的。 那么moc在这里做什么?

插槽可以有返回值 ,所以我们现在可以连接一个返回值的插槽到一个返回值的信号? 毕竟这可能吗? 如果是这样,有用吗?

编辑:我不是要求解决方法,所以请不要提供任何。

编辑:它显然是没有用的Qt::QueuedConnection模式(既QPrintPreviewWidget API ,但仍然存在,是有用的)。 但Qt::DirectConnectionQt::BlockingQueuedConnection (或Qt::AutoConnection ,当它parsing为Qt::DirectConnection )呢?

好。 所以,我做了一些调查。 看来这是可能的。 我能够发出一个信号,并从信号连接到的插槽接收值。 但问题是,它只是从多个连接的插槽中返回最后的返回值:

这是一个简单的类定义( main.cpp ):

 #include <QObject> #include <QDebug> class TestClass : public QObject { Q_OBJECT public: TestClass(); Q_SIGNALS: QString testSignal(); public Q_SLOTS: QString testSlot1() { return QLatin1String("testSlot1"); } QString testSlot2() { return QLatin1String("testSlot2"); } }; TestClass::TestClass() { connect(this, SIGNAL(testSignal()), this, SLOT(testSlot1())); connect(this, SIGNAL(testSignal()), this, SLOT(testSlot2())); QString a = emit testSignal(); qDebug() << a; } int main() { TestClass a; } #include "main.moc" 

当主运行时,它构造了一个testing类。 构造函数将两个插槽连接到testSignal信号,然后发出信号。 它捕获从调用的插槽返回的值。

不幸的是,你只能得到最后的返回值。 如果你评估上面的代码,你会得到:“testSlot2”,从信号的连接插槽的最后返回值。

这是为什么。 Qt Signals是信号模式的语法加糖接口。 老虎机是信号的接收者。 在一个直接连接的信号槽关系中,你可以把它看作类似于(伪代码)的:

 foreach slot in connectedSlotsForSignal(signal): value = invoke slot with parameters from signal return value 

moc显然在这个过程中做了一些帮助(基本types检查等),但是这有助于画图。

不,他们不可能。

Boost ::信号与Qt中的信号完全不同。 前者提供了一个先进的callback机制,后者实际上实现了信令习惯。 在multithreading环境中工作时,Qt(交叉线程)信号依赖于具有队列的消息泵,因此信号在某些时间点(发射器线程未知)被asynchronous调用。

你可以从Qt signal得到一个返回值,代码如下:

我的例子显示了如何使用Qt signal来读取QLineEdit的文本。 我只是扩展@jordan提出的:

应该可以通过这种方式来修改代码,以便使用作为“返回”的“out”参数。

 #include <QtCore> #include <QtGui> class SignalsRet : public QObject { Q_OBJECT public: SignalsRet() { connect(this, SIGNAL(Get(QString*)), SLOT(GetCurrentThread(QString*)), Qt::DirectConnection); connect(this, SIGNAL(GetFromAnotherThread(QString*)), SLOT(ReadObject(QString*)), Qt::BlockingQueuedConnection); edit.setText("This is a test"); } public slots: QString call() { QString text; emit Get(&text); return text; } signals: void Get(QString *value); void GetFromAnotherThread(QString *value); private slots: void GetCurrentThread(QString *value) { QThread *thread = QThread::currentThread(); QThread *mainthread = this->thread(); if(thread == mainthread) //Signal called from the same thread that SignalsRet class was living ReadObject(value); else //Signal called from another thread emit GetFromAnotherThread(value); } void ReadObject(QString *value) { QString text = edit.text(); *value = text; } private: QLineEdit edit; }; 

要使用这个,只需要call();

Qt的qt_metacall函数返回一个整数状态码。 正因为如此,我相信这使得实际的返回值是不可能的(除非你在预编译之后使用元对象系统和moc文件)。

但是,您可以使用正常的function参数。 应该可以通过这种方式来修改代码,以便使用作为“返回”的“out”参数。

 void ClassObj::method(return_type * return_) { ... if(return_) *return_ = ...; } // somewhere else in the code... return_type ret; emit this->method(&ret); 

您可以尝试使用以下方法解决此问题:

  1. 所有连接的插槽必须将其结果保存在可从信号对象访问的某个位置(容器)中
  2. 最后连接的插槽应该以某种方式(select最大值或最后一个值)处理收集的值,并暴露唯一的一个
  3. 发射物体可以尝试访问这个结果

就像一个想法。

Interesting Posts