QVector<custom class> 连接线程无法对类型的参数进行排队
QVector<custom class> connection thread cannot queue arguments of type
我有问题。
我有一个自定义 class BasicSpace
。这个 class 不是 qobject
(没有宏)并且不被 qobject
继承。它很简单 class 有一些数据,qtime 等。
我有:
connect(connector,SIGNAL(finishedReadData(QVector<BasicSpace>&)),&window,SLOT(updateData(QVector<BasicSpace>&)));
我试试
qRegisterMetaType< QVector<BasicSpace> >("QVector<BasicSpace>");
在 main.cpp
.
但是 Qt 仍然在调用 slot 时带我消息:
QObject::connect: Cannot queue arguments of type 'QVector&'
(Make sure 'QVector&' is registered using qRegisterMetaType().)
我的注意力在线程之间。
我的项目是高级的,所以我尽量避免 typedef
不同名称的解决方案,所以我没有测试它。
有人可以帮助我吗?
编辑
THX 弗兰克。我替换了对 QVector 之类的值的引用,没有 &。这项工作,但我有疑问。它有效,但线程连接总是复制数据,所以没有参考数据的 prabodly 是双重复制,第一次在函数中,第二次在线程之间?
我觉得已经解决了 50%。我有工作代码,但主要问题 - 排队连接中模板类型的参考值未解决。
当您连接同一线程中的信号和对象槽时,将使用 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
时被销毁。
- 控制returns到事件循环并执行
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/
我有问题。
我有一个自定义 class BasicSpace
。这个 class 不是 qobject
(没有宏)并且不被 qobject
继承。它很简单 class 有一些数据,qtime 等。
我有:
connect(connector,SIGNAL(finishedReadData(QVector<BasicSpace>&)),&window,SLOT(updateData(QVector<BasicSpace>&)));
我试试
qRegisterMetaType< QVector<BasicSpace> >("QVector<BasicSpace>");
在 main.cpp
.
但是 Qt 仍然在调用 slot 时带我消息:
QObject::connect: Cannot queue arguments of type 'QVector&' (Make sure 'QVector&' is registered using qRegisterMetaType().)
我的注意力在线程之间。
我的项目是高级的,所以我尽量避免 typedef
不同名称的解决方案,所以我没有测试它。
有人可以帮助我吗?
编辑 THX 弗兰克。我替换了对 QVector 之类的值的引用,没有 &。这项工作,但我有疑问。它有效,但线程连接总是复制数据,所以没有参考数据的 prabodly 是双重复制,第一次在函数中,第二次在线程之间?
我觉得已经解决了 50%。我有工作代码,但主要问题 - 排队连接中模板类型的参考值未解决。
当您连接同一线程中的信号和对象槽时,将使用 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
时被销毁。- 控制returns到事件循环并执行
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/