我有问题。
我有一个自定义类BasicSpace
。此类不是qobject
(没有宏),并且不由qobject
继承。这是一个简单的类,有一些数据,qtime等。
我有:
connect(connector,SIGNAL(finishedReadData(QVector<BasicSpace>&)),&window,SLOT(updateData(QVector<BasicSpace>&)));
我试试
qRegisterMetaType< QVector<BasicSpace> >("QVector<BasicSpace>");
main.cpp
中的。
但Qt仍然在调用插槽时带我发信息:
QObject :: connect:无法对“QVector&amp;”类型的参数进行排队 (确保使用qRegisterMetaType()注册'QVector&amp;'。)
我的注意力集中在线程上。
我的项目是高级的,所以我尝试避免使用不同名称的typedef
解决方案,所以我不测试它。
有人可以帮帮我吗?
EDIT THX Frank。我将QVector替换为值的引用,没有&amp ;.这项工作,但我怀疑。它工作但线程连接总是复制数据,所以没有参考数据的prabodly是双倍复制,第一次在函数和第二次线程之间?
我认为50%已经解决了。我有工作代码,但主要问题 - 排队连接中模板类型的引用值尚未解决。
答案 0 :(得分:0)
当您连接信号和位于同一线程中的对象插槽时,将使用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/