2013-06-12 2 views
3

В моем приложении qt у меня есть класс (рабочий), который вызывается из объекта, который работает в потоке. В моем классе рабочего я создать QList, как этотПередача QList <QString> * к сигналу от QThread

QList <QString> albums; 

while (i.hasNext()) 
{ 
    QRegularExpressionMatch album = i.next(); 
    albums.append(album.captured("album")); 
} 
emit SignalGotAlbums(albums); 

Я получаю этот сигнал в другом классе, который оборачивает мой рабочий, для нарезания использования. Давайте назовем этот класс GetAlbumsThread. В там я успешно получить SignalGotAlbums в слоте

void GetAlbumsThread::Reply(QList <QString> &list) 
{ 

emit gotAlbums(list); 
emit finished(); 
} 

В этом слоте I'am стрельбы другого сигнал gotAlbums, который предполагает, чтобы быть связан с прорезью в моей графической оболочке нити, и передать мою QList там. Моя проблема в том, что когда я пытаюсь передать QList из потока в gui, он просто не работает! Слот не получает сигнал gotAlbums;

Сигнал объявляется так:

void gotAlbums(QList<QString> &); 

И подключен к моему графического интерфейса слот (конечно в моей графической оболочки нити) так:

private slots: 
    void AlbumsReceived(QList<QString> &list) 
    ... 

    QThread* albumsThread = new QThread(); 

    GetAlbumsThread *albumsObject = new GetAlbumsThread(); 

    albumsObject->moveToThread(albumsThread); 

    connect(albumsThread, SIGNAL(started()), albumsObject, SLOT(process())); 

    connect(albumsObject, SIGNAL(gotAlbums(QList<QString> &)), this, SLOT(AlbumsReceived(QList<QString> &)); 

    albumsThread->start(); 

AlbumsReceived никогда не получить называеться по какой-то причине. connect возвращает true. Может кто-то помочь мне с этим. Я думаю, что проблема заключается в передаче QList между потоками.

+0

Если я что-то отсутствует, вы создаете альбомы QList в качестве локальной переменной в стеке, затем передавая ссылку на него в вашем сигнале, а это значит, что QList мог выйти из области действия и был уничтожен на время, когда очереди с очередями вернутся к потоку графического интерфейса. Это не должно помешать слоту, принимающему сигнал, но потенциально может быть неприятной ошибкой. – Ninjammer

+0

Должен ли я сделать глобальный QList? или создать его с новым? – SirLanceloaaat

+0

btw Я также пытался сделать QList в кучу, по Calline new Qlist , но я получаю недействительное приложение 'sizeof' для неполного типа 'QStaticAssertFailure ' error – SirLanceloaaat

ответ

3

Проблема здесь в том, что вы используете ссылку для вашего сигнала/слот, то есть в QList<QString> &. Это несовместимо с потоками, поскольку они используют свой собственный стек, и в этом случае то, что вы делаете, это передать указатель на объект в стеке из одного потока в другой.

Возможности:

  1. Используйте сырые QList<QString> сигналы/слоты, которые заставят копию.
  2. Выделите QList<QString> с помощью new (следовательно, он будет находиться в куче вместо стека) и используйте QList<QString> * сигналы/слоты.

Следующий код иллюстрирует эти два метода:

// A.h 

#include <QObject> 
#include <QDebug> 

class A: public QObject 
{ 
Q_OBJECT 

public slots: 
    void foo(int i) { qDebug() << i; } 
    void bar(QList<int> l) { foreach(int i, l) qDebug() << i; } 
    void bar2(QList<int> * l) { foreach(int i, *l) qDebug() << i; } 
}; 


// Worker.h 

#include <QObject> 

class Worker: public QObject 
{ 
    Q_OBJECT 

public slots: 
    void process() 
{ 
     // pass an int 
     emit foo(1); 

     // pass a list by value 
     emit bar(QList<int>() << 2 << 3 << 4); 

     // pass a poniter to a list 
     list = new QList<int>(); 
     *list << 5 << 6 << 7; 
     emit bar2(list); 

     emit finished(); 
    } 

signals: 
    void finished(); 
    void foo(int); 
    void bar(QList<int>); 
    void bar2(QList<int> *); 

private: 
    QList<int> * list; 
}; 


// main.cpp 

#include <QApplication> 
#include <QThread> 
#include <QObject> 

#include "A.h" 
#include "Worker.h" 

int main(int argc, char** argv) 
{ 
    QApplication app(argc, argv); 

    A * a = new A(); 
    Worker * worker = new Worker(); 
    QObject::connect(worker, SIGNAL(foo(int)), a, SLOT(foo(int))); 
    QObject::connect(worker, SIGNAL(bar(QList<int>)), a, SLOT(bar(QList<int>))); 
    QObject::connect(worker, SIGNAL(bar2(QList<int>*)), a, SLOT(bar2(QList<int>*))); 

    QThread * thread = new QThread(); 
    worker->moveToThread(thread); 

    QObject::connect(thread, SIGNAL(started()), worker, SLOT(process())); 
    QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit())); 
    QObject::connect(thread, SIGNAL(finished()), &app, SLOT(quit())); 
    thread->start(); 

    return app.exec(); 
} 

Выход:

1 
2 
3 
4 
5 
6 
7 
+0

Пробовал p2. Я получаю сообщение об ошибке с распределением кучи QList: «Недействительное приложение« sizeof »для неполного типа« QStaticAssertFailure ». – SirLanceloaaat

+0

@SirLanceloaaat Вы изменили определение сигнала и слота с помощью 'QList *' вместо 'QList '? См. Мое редактирование для полного рабочего примера. – Boris

+0

Да, я изменил определения слота сигнала, но все равно получаю ошибку QStaticAssertFailure (требуется определение метатипа blabla). Поэтому я просто изменил определения и QList * на QStringList *, теперь он отлично работает. Тай за помощью. – SirLanceloaaat

3

Вы пытались зарегистрировать свой объект QList перед вызовом Object :: connect (...)?

Вы можете объявить мета-используя этот код:

qRegisterMetaType< QList<QString> >("QList<QString>"); 
+0

попробовал это до подключения, ничего не меняет. – SirLanceloaaat