Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] Slots from a base class will not be called when subclassing it

[SOLVED] Slots from a base class will not be called when subclassing it

Scheduled Pinned Locked Moved General and Desktop
8 Posts 3 Posters 3.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    Coastcrawler
    wrote on 19 Apr 2014, 20:07 last edited by
    #1

    Now, starting with Qt/qml I want to use my own threading class, based on
    QThread. I've read some articles, threads and blogs about QThread and learned
    that it is better not to subclass QThread directly but to implement a class
    that will instantiate a QThread object and use the moveToThread() method, what
    I finally did.

    So far it runs nicely, a thread may be created and started. But, as the following code is just the base implementation I want to subclass it for each thread I am going to use in my application. And then, the problem begins. In the ThreadBase class I have connected a slot (onThreadFinished()) to be called when the QThread finally has stopped working to delete the QThread instance.

    But that slot won't be called as soon as I have a derived implementation of the process() method.

    To be a bit more precise, here is the complete code:

    ThreadBase.h
    @
    #if(!defined(THREAD_BASE_H))
    #define THREAD_BASE_H

    #include "ThreadWorker.h"
    #include <QObject>

    class QThread;

    class ThreadBase : public QObject
    {
    Q_OBJECT

    public:
    ThreadBase(QString qstrObjectName = QString("USER_THREAD"));
    virtual ~ThreadBase();

    signals:
    void processingFinished();
    void error(QString qstrError);

    protected slots:
    virtual void process();
    virtual void onThreadFinished();
    virtual void onError(QString qstrError);

    protected:
    QThread* m_pThread;

    private:
    };

    #endif // THREAD_BASE_H
    @

    ThreadBase.cpp
    @

    #include <QThread>
    #include <QDebug>

    #include "ThreadBase.h"

    ThreadBase::ThreadBase(QString qstrObjectName)
    //: ThreadWorker()
    : QObject()
    {
    // create thred instance and pass over this worker instance
    m_pThread = new QThread;

    if(m_pThread)
    {
    m_pThread->setObjectName(qstrObjectName);
    this->moveToThread(m_pThread);

    connect(m_pThread,  SIGNAL(started()),            this,      SLOT(process()));
    connect(this,       SIGNAL(processingFinished()), m_pThread, SLOT(quit()));
    connect(this,       SIGNAL(processingFinished()), m_pThread, SLOT(deleteLater()));
    connect(m_pThread,  SIGNAL(finished()),           this,      SLOT(onThreadFinished()));
    
    m_pThread->start();
    

    }
    }

    ThreadBase::~ThreadBase()
    {
    delete m_pThread;
    }

    void ThreadBase::process()
    {
    qDebug("El Processo says: 'Base process() implementation... even if it's boring, nothing should ever happen here...'");
    emit processingFinished();
    }

    void ThreadBase::onThreadFinished()
    {
    qDebug() << "El Finito says: 'Thread " + m_pThread->objectName() + " has been shutted down... instance of ThreadBase may be destroyed now'";
    delete m_pThread;
    }

    void ThreadBase::onError(QString qstrError)
    {
    qDebug() << qstrError;
    }
    @

    That's for the base implementation. As said before, as long as I do not re-implement the process() method, the onThreadFinished() slot will be called as desired.

    Now for the derived class:

    MainLoop.h
    @
    #if(!defined(MAIN_LOOP__H))
    #define MAIN_LOOP__H

    #include "thread/ThreadBase.h"

    class MainLoop : public ThreadBase
    {
    Q_OBJECT

    public:
    MainLoop();
    virtual ~MainLoop();

    //re-implementation of process method to do some stuff...
    virtual void process();
    

    private:
    };

    #endif //MAIN_LOOP__H
    @

    MainLoop.cpp

    @
    #include "MainLoop.h"

    #include <QDebug>

    MainLoop::MainLoop()
    : ThreadBase("MAIN_LOOP")
    {
    }

    MainLoop::~MainLoop()
    {
    }

    void MainLoop::process()
    {
    qDebug("El Processo says: 'running Main Loop...'");
    }
    @

    When instatiating a MainLoop object, the processing will run perfectly, but the desired slot is never called.

    Now I hope someone here is able to enlighten me, what I have done wrong :)

    Best wishes,
    Coastcrawler

    ------------------------ SOLUTION: see last reply: http://qt-project.org/forums/viewreply/172919/

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 19 Apr 2014, 20:17 last edited by
      #2

      Hi and welcome to devnet,

      The problem is that in MainLoop, you don't declare process as a slot so it's a normal function.

      On a side note:

      @
      if(m_pThread)
      {@

      Is not really useful, if the allocation of m_pThread fails, your application has exhausted the available memory and will probably get killed by the system.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • C Offline
        C Offline
        Coastcrawler
        wrote on 20 Apr 2014, 08:13 last edited by
        #3

        Hi SGaist,

        thanks for your welcome and your fast reply.

        I've just tried to as you wrote:

        @
        protected slots:
        virtual void process();
        @

        in the MainLoop.h to declare as a slot but it won't change the behaviour. The slot is still not called.

        And, what I found out was: the delete line in the ThreadBase::onThreadFinished() not only seems to be pointless as the Slot

        @
        connect(this, SIGNAL(processingFinished()), m_pThread, SLOT(deleteLater()));
        @

        will do the job of deleting the instance, it might also be dangerous as you never now if the thread is running, right? So, maybe the processingFinished() slot is just needless and the problem seems to be solved.

        But, in that case, how do I make sure all the other slots are called in the right manner?

        Best Regards,
        Coast

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 20 Apr 2014, 20:13 last edited by
          #4

          Did you do a clean rebuild after you add the "protected slots" to MainLoop ?

          What do you mean by "right manner" ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • C Offline
            C Offline
            Coastcrawler
            wrote on 21 Apr 2014, 12:14 last edited by
            #5

            Well, with "the right manner" I meant how to check wether a slot is executed on the signals arrival or not.

            But anyway... I am just reading a blog ( http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1 ) I guess, I just need much more knowledge and comprehension about Qt's signal/slot and threading system. Until then, we can stop at that stage of discussion.

            Thank you for your assistance. As soon as I found out about my problem, I will share my knowledge here :)

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 21 Apr 2014, 20:39 last edited by
              #6

              You're welcome !

              You can also read the latest QThread "documentation":http://qt-project.org/doc/qt-5/qthread.html all cases are now described

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • A Offline
                A Offline
                adolby
                wrote on 21 Apr 2014, 21:36 last edited by
                #7

                The reason ThreadBase::onThreadFinished() isn't getting executed is because you override the method where the ThreadBase::processingFinished() signal is emitted. To remedy this, you could call ThreadBase::process() from MainLoop::process().

                The docs answer your question about deleteLater: http://qt-project.org/doc/qt-5/qobject.html#deleteLater

                1 Reply Last reply
                0
                • C Offline
                  C Offline
                  Coastcrawler
                  wrote on 22 Apr 2014, 16:44 last edited by
                  #8

                  omfg... yes...

                  Well... might be a beginners failure XD

                  As I said, I need much more time until I really get used to the signal/slot mechanism.

                  Thank you adolby and SGaist for your assistance :)

                  1 Reply Last reply
                  0

                  8/8

                  22 Apr 2014, 16:44

                  • Login

                  • Login or register to search.
                  8 out of 8
                  • First post
                    8/8
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved