20 ways to debug Qt signals and slots

Below are some suggestions for troubleshooting signals and slots in the Qt C++ library.

1. Check for compiler warnings about non-existent signals and/or slots.

2. Use break points or qDebug to check that signal and slot code is definitely reached:
- the connect statement
- code where the signal is fired
- the slot code.

3. Check that the parameter types of the signal and slot are exactly correct and, as appropriate, that they match.

4. Make sure you haven’t added a name to the signal or slot argument: for example, use textChanged(const QString &) not textChanged(const QString &text).

5. Check that the connect argument types and syntax are correct. The connect statement should look like this: 

connect(senderObject, SIGNAL(mySignal(const QString&)), receiverObject, SLOT(mySlot(const QString&)));

Check brackets, check that SIGNAL and SLOT are capitalised and that the sender and receiver are both objects, not class names.

6. Check that the signal is being fired as expected. You can do this with code like the following:
connect(this, SIGNAL(mySignal()), qApp, SLOT(aboutQt()));

7. Check that slots are declared correctly in the appropriate public/protected/private slots sections of your class declaration. Check that you’ve used private slots:, for example not slots:. Check for a colon, i.e. private slots: not private slots.

8. If you use custom signals, check that these are declared correctly, with a void return type, in the public/protected/private signals section of your class declaration.

9. Make sure the Q_OBJECT macro is inserted at the beginning of your class declaration.

10. Check that classes using signals and slots inherit QObject or a QObject subclass.

11. Make sure to run qmake after adding the Q_OBJECT macro to a class. You may need to rebuild your project.

12. Use break points or qDebug to check that slots are being called the appropriate number of times: make sure the connection isn’t made repeatedly.

13. Put all connect statements before functions calls that may fire their signals, to ensure that the connections are made before the signals are fired. For example:

   _myObj = new MyClass();
   connect(_myObj, SIGNAL(somethingHappend()), SLOT(doSomething()));
   _myObj->init();

not


   _myObj = new MyClass();
   _myObj->init();
   connect(_myObj, SIGNAL(somethingHappend()), SLOT(doSomething()));


14. Check that your connections aren't affected by disconnect statements.

15. Don't add a semi-colon after Q_OBJECT:

   {
   Q_OBJECT
   ...
   }

not

   {
   Q_OBJECT;
   ... 
   }

16. Check the return value of the connect statement: connect returns true if it successfully connects the signal to the slot.

17. Use QErrorMessage::qtHandler() or qInstallMsgHandler() to view connect error warnings.

18. Make sure that your slot function is declared as a slot, e.g. private slots not private.

19. Use QSignalSpy to verify signal arguments.

20. Follow Qt's naming conventions for signals and slots:

signal: somethingHappened()
slot: doSomething()

In grammatical terms, signal names are usually constructed from a past participle: changed, pressed, etc. They describe an event or change of state that has occurred. Slot names are imperative verbs and describe an action to be done: clear, setDate, etc.

About these ads

About Sam Dutton

I am a Developer Advocate for Google Chrome. I grew up in rural South Australia, went to university in Sydney, and have lived since 1986 in London, England. Twitter: @SW12
This entry was posted in Uncategorized and tagged , , , . Bookmark the permalink.

21 Responses to 20 ways to debug Qt signals and slots

  1. Newbie says:

    Thanks for this. It solved a problem I was having with signals and slots (Calling the signal in the constructor before I had connected them)

  2. Stefan says:

    Hey; I’ve got a new one. I came across this post trying to figure my problem out. Turned out I’d declared a widget inside a conditional. No wonder it disappears – it’s going out of scope! Possibly worse than that time I used = instead of ==.

  3. Anisha Kaul says:

    Thanks Sam, your blog saved my time.

  4. Ryan Cuthbertson says:

    21. Ensure the receiving objects you connect to are not getting destroyed before their slots can get called.

  5. Thanks for the post. I always put the parameter name in the connect statement and wonder, why doesn’t my program work. :P Saved a great deal.

  6. ANIL V says:

    Hi Sam,
    I am trying to emit the signal for same class of slot for that i have used as mentioned below in my constructor:
    connect( this,SIGNAL(send_sig(int)),this,SLOT(receiver(int));
    From the one of same class member i am emitting sigma but the slot is not getting calling. I have verified this with the qDebug();

    Can you please help me in this ?

    Thanks

  7. Jamie says:

    Awesome! Your article (in particular point 4) just saved me a lot of effort debugging some signal/slot issues in my BB10 Cascades app.

  8. Brian says:

    Thanks! I didn’t declare the slot and this checklist saved me. I’d forgotten how time consuming C++ development is :D

  9. Pingback: Qt 4′ten Qt 5′e Geçiş | D. Barış Akkurt

  10. Number 5 was the key for me. Thanks so much!

  11. Jay says:

    Helpful article , it helped alot after reading this article solved the 6 hrs screwing problem.

  12. Thank you very much for the post. Excellent advice and has helped me out of more than one bind at this point.

  13. Someone says:

    To extend on >Ryan Cuthbertson – 27 January, 2012 at 4:02 am – “21. …”<:
    This could also be the case when re-emitting a signal, in my case, the re-emitting object (and its original signal source child) was created locally in the main window constructor. Creating it with the new keyword fixed the problem..

  14. John says:

    Thanks for the posting, let me add my own in case it saves someone else the hours I wasted.

    23 Don’t instantiate objects using symbols until after the QApplication object is created. Seems obvious but I put my single instance code at the top of my main and then had a heck of a time figuring out why nothing was emitting signals.

    John

  15. Colin Hobday says:

    I have the following…

    m_phone = new Phone(this);
    connect( m_phone, SIGNAL(callUpdated(const bb::system::phone::Call &)), this, SLOT(callUpdated(const bb::system::phone::Call &)));//,Qt::QueuedConnection);
    connect(m_phone,SIGNAL(lineUpdated(const bb::system::phone::Line &)),this,SLOT(lineUpdated(const bb::system::phone::Line &)),Qt::QueuedConnection);
    connect(m_phone,SIGNAL(lineRemoved(const bb::system::phone::Line &)),this,SLOT(lineRemoved(const bb::system::phone::Line &)),Qt::QueuedConnection);
    ———————–
    callUpdated works just fine – but I NEVER get a lineUpdated or lineRemoved signal. Can you tell why this is.
    I need lineUpdated to work as the info I want is in the Line object – but will only be populated once the lineUpdated signal has fired.

    Any ideas would be useful.

  16. elyse prewitte says:

    Many thanks, this was a lifesaver.

  17. rigo says:

    Thank you for this great article!
    On my browser, the formatting seems to get garbled after point 13.

  18. juanjuan says:

    Great one !!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s