当您连接位于同一线程中的信号和对象槽时,将使用Qt::DirectConnection 类型。在这种情况下,插槽作为普通函数调用执行。您不必通过qRegisterMetaType 注册您的数据类型,并且当您将数据作为参考发送时,它不会被复制。
当发送者和接收者对象不在同一个线程中时,使用Qt::QueuedConnection 类型。现在,当您发送一些数据时,它会被复制到事件队列中,无论您是按值发送还是通过引用发送。此外,您的数据类型必须使用qRegisterMetaType 注册。
这是一个说明这种行为的简单示例:
class MyObject
{
public:
MyObject()
{
qDebug() << Q_FUNC_INFO;
}
MyObject(const MyObject &other)
{
qDebug() << Q_FUNC_INFO;
}
~MyObject()
{
qDebug() << Q_FUNC_INFO;
}
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
signals:
void myObjectSignal1(const MyObject &obj);
void myObjectSignal2(const MyObject &obj);
public slots:
void testDirectConnection();
void testQueuedConnection();
void myObjectSlot(const MyObject &obj);
};
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *layout = new QHBoxLayout(this);
QPushButton *b1 = new QPushButton;
b1->setText("direct");
layout->addWidget(b1);
connect(b1, SIGNAL(clicked()), this, SLOT(testDirectConnection()));
QPushButton *b2 = new QPushButton;
b2->setText("queued");
layout->addWidget(b2);
connect(b2, SIGNAL(clicked()), this, SLOT(testQueuedConnection()));
qRegisterMetaType<MyObject>("MyObject");
connect(this, SIGNAL(myObjectSignal1(MyObject)),
this, SLOT(myObjectSlot(MyObject)));
connect(this, SIGNAL(myObjectSignal2(MyObject)),
this, SLOT(myObjectSlot(MyObject)), Qt::QueuedConnection);
}
Widget::~Widget()
{
}
void Widget::testDirectConnection()
{
MyObject obj;
emit myObjectSignal1(obj);
}
void Widget::testQueuedConnection()
{
MyObject obj;
emit myObjectSignal2(obj);
}
void Widget::myObjectSlot(const MyObject &obj)
{
}
Qt::DirectConnection 场景:
myObjectSignal1 信号连接到myObjectSlot 使用
Qt::DirectConnection。
MyObject 在Widget::testDirectConnection 内部创建。
myObjectSignal1 信号触发 myObjectSlot 作为正常的函数调用。
-
MyObject 通过引用传递到 myObjectSlot。
-
myObjectSlot 执行完成。
-
MyObject 在控制离开 Widget::testDirectConnection 时被销毁。
输出将是:
MyObject::MyObject()
MyObject::~MyObject()
Qt::QueuedConnection 场景:
-
myObjectSignal2 信号连接到 myObjectSlot 使用
Qt::QueuedConnection。
MyObject 在 Widget::testQueuedConnection 内部创建。
myObjectSignal2 信号触发,MyObject 被复制到事件队列中。
-
MyObject 在控制离开 Widget::testQueuedConnection 时被销毁。
- 控制返回到事件循环并执行
myObjectSlot,得到MyObject的副本。
-
MyObject 的副本在控制权离开 myObjectSlot 时被销毁。
输出将是:
MyObject::MyObject() // object is created inside testQueuedConnection
MyObject::MyObject(const MyObject&) // object is copied
MyObject::~MyObject() // object is destroyed
MyObject::~MyObject() // copy is destroyed
如果您想避免额外的对象复制,您可以使用new 运算符在堆上为您的数据分配内存,然后传递一个指针。但在这种情况下,您必须确保您的对象在处理结束时被销毁。
一篇关于 Qt 信号槽连接中参数复制的好文章:http://www.embeddeduse.com/2013/06/29/copied-or-not-copied-arguments-signals-slots/