Boost.Signals允许various strategies使用槽的返回值来形成信号的返回值。例如。添加它们,从它们中形成一个vector
,或者返回最后一个。
常见的智慧(在Qt文档中表达[编辑:以及对这个问题的一些答案])是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返回类型的信号,它似乎以允许返回值传递的方式主动实现它:
// 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在这做什么?
Slots can have return values,那么我们可以将带有返回值的槽连接到具有返回值的信号吗?毕竟,这可能吗?如果是这样,它有用吗?
编辑:我不是要求解决方法,所以请不要提供任何解决方法。
编辑:它显然在Qt::QueuedConnection
模式中没有用(虽然QPrintPreviewWidget API也不是,但它仍然存在并且很有用)。但是Qt::DirectConnection
和Qt::BlockingQueuedConnection
(或Qt::AutoConnection
,当它解析为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"
主运行时,它构造一个测试类。构造函数将两个插槽连接到testSignal信号,然后发出信号。它从被调用的槽中捕获返回值。
不幸的是,您只能获得最后的返回值。如果你评估上面的代码,你会得到:“testSlot2”,来自信号连接槽的最后一个返回值。
这就是原因。 Qt信号是信令模式的语法糖界面。插槽是信号的接收者。在直接连接的信号槽关系中,你可以认为它类似于(伪代码):
foreach slot in connectedSlotsForSignal(signal):
value = invoke slot with parameters from signal
return value
显然,moc在这个过程中做了一点帮助(基本类型检查等),但这有助于绘制图片。
不,他们不能。
Boost::signals
与Qt中的完全不同。前者提供了高级回调机制,而后者实现了信令习惯用法。在多线程环境中,Qt(交叉线程)信号依赖于消息队列,因此它们在一些(发射器线程未知)的时间点被异步调用。
Qt的qt_metacall函数返回一个整数状态代码。因此,我认为这使得实际返回值无法实现(除非您在预编译后使用元对象系统和moc文件)。
但是,您可以使用正常的功能参数。应该可以修改代码,以便使用充当“返回”的“out”参数。
void ClassObj::method(return_type * return_)
{
...
if(return_) *return_ = ...;
}
// somewhere else in the code...
return_type ret;
emit this->method(&ret);
您可以使用以下代码从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();
。
您可以尝试使用以下方法解决此问题:
就像一个想法。