QVector<自定义类>连接线程无法排队类型的参数



我有问题。我有一个自定义类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&"的参数进行排队 (确保使用 qRegisterMetaType(( 注册"QVector"。

我的注意力在线程之间。

我的项目很先进,所以我尽量避免使用typedef不同名称的解决方案,所以我不测试它。有人可以帮助我吗?

编辑谢谢弗兰克。我替换了对值的引用,例如 QVector,没有 &.这项工作,但我有疑问。它可以工作,但线程连接总是复制数据,所以没有参考数据是双重复制,第一次在功能中,第二次在线程之间?

我说这已经解决了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方案:

  1. myObjectSignal1信号连接到myObjectSlot使用 Qt::DirectConnection .

  2. MyObject是在 Widget::testDirectConnection 中创建的。

  3. myObjectSignal1信号触发myObjectSlot作为正常的函数调用。

  4. MyObject通过引用传递到 myObjectSlot 中。
  5. myObjectSlot执行完成。
  6. MyObject随着控制离开Widget::testDirectConnection而被摧毁。

输出将是:

MyObject::MyObject() 
MyObject::~MyObject() 

Qt::QueuedConnection方案:

  1. myObjectSignal2信号连接到myObjectSlot Qt::QueuedConnection .
  2. MyObject是在Widget::testQueuedConnection中创建的。

  3. myObjectSignal2信号触发器和MyObject被复制到事件队列中。

  4. 当控件离开Widget::testQueuedConnection时,MyObject被破坏。
  5. 控件返回到事件循环并执行myObjectSlot,从而获得MyObject的副本。
  6. 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/

相关内容

最新更新