1

I have a Qt application that was developed using Qt Creator and the GUI tool that accompanies it. I have a main thread, TheGui and a worker thread that is created by the main thread, WorkerThread (called thread).

The problem I'm having is when I create a slot in the GUI by using

public slot:
  void updateTable(string str);

within the header file of the GUI and signal void sendList(string str); within the header file of the worker thread, the slot never gets called. I connected the two using

connect(&thread, SIGNAL(sendList(string str),
        this,    SLOT(updateTable(string str)));

within the constructor in the GUI cpp file. I did something similar except with the slot in the worker thread and signal from the GUI and it worked fine. I know from using the debugger that the signal sendList is indeed getting called, it is just never going into it.

Any thoughts?

RAM
  • 2,257
  • 2
  • 19
  • 41
Kyle Kurtz
  • 13
  • 1
  • 3

2 Answers2

4
  1. Because the signal and the slot are on distinct threads, the connection between them has the Qt::QueuedConnection type. And for queued connections, Qt has to be able to save a copy of the signal parameters, to pass them later to the slot.
    So, to inform Qt that the type is copyable, you have to register it with Qt's meta-object system (see QMetaType) like this:

    // This macro call should be put in one of your .h files 
    Q_DECLARE_METATYPE(std::string)
    
    // You should call this function before any (queued) 
    // signal/slot connection involving the type
    qRegisterMetaType<std::string>();
    
  2. The parameter name shouldn't be included in the QObject::connect call, and the type names should be exactly the same as the ones you passed to Q_DECLARE_METATYPE:

    connect(&thread, SIGNAL(sendList(std::string), this, SLOT(updateTable(std::string)));
    

You can also use QString or QByteArray, which are already registered, instead of std::string, since these functions are slots and signals and as such are already Qt specific.

alexisdm
  • 29,448
  • 6
  • 64
  • 99
  • Thanks for the response! I actually got around this for the time being by using pointers. Where would I call qRegisterMetaType? I keep getting error 'instantiated from 'int qMetaTypeId(T*)[with T=StringVector]' where StringVector is what I'm trying to declare. – Kyle Kurtz Oct 26 '11 at 21:07
  • @Kyle Maybe you didn't include the header file where you used Q_DECLARE_METATYPE in the .cpp file where you called qRegisterMetaType. – alexisdm Oct 26 '11 at 22:19
  • Is there a required place in the header you need to put it? Under Q_OBJECT? Also, I have switched to using a QVector and passing that using slots. Based on documentation I've been looking at, this isn't registered automatically either? – Kyle Kurtz Oct 28 '11 at 22:37
  • Q_DECLARE_METATYPE should be outside any class declaration. You can use `QStringList` instead which should be registered. – alexisdm Oct 28 '11 at 23:29
  • Turns out the problem was i needed a space between the < and the type within qRegisterMetaType and to keep the macro outside of the class declaration. Now it all works! – Kyle Kurtz Nov 02 '11 at 13:17
1

Sure that connection is actually made? If there are any problems with connect call, there is usually some debugging output about it on cerr.

Secondly, I think you have a typo - if you copied connect call from your code, then know that you have parenthesis missing around SIGNAL - should be

connect(&thread, SIGNAL(sendList(string)), this, SLOT(updateTable(string)));

Thirdly, what is that you are passing as signal/slot parameter? Is it std::string? Connections between threads must be queued connections. Queued connections can use as parameters only types declared with Q_DECLARE_METATYPE macro, and registered with qRegisterMetaType. As far as I know, Qt by default doesn't declare those for std::string, as it prefers QString. If you didn't add those to your code, it might be the reason for failure.

RAM
  • 2,257
  • 2
  • 19
  • 41
j_kubik
  • 6,062
  • 1
  • 23
  • 42