Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Why isn't my signal and slot working? Button click (signal) is supposed to start a thread (slot).

    General and Desktop
    2
    8
    3743
    Loading More Posts
    • 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.
    • T
      tahayassen last edited by

      mainwindow.h:

      @#ifndef MAINWINDOW_H
      #define MAINWINDOW_H

      #include <QMainWindow>

      namespace Ui {
      class MainWindow;
      }

      class MainWindow : public QMainWindow
      {
      Q_OBJECT

      public:
      explicit MainWindow(QWidget *parent = 0);
      ~MainWindow();

      private slots:

      private:
      Ui::MainWindow *ui;
      };

      #endif // MAINWINDOW_H@

      myobject.h:

      @#ifndef MYOBJECT_H
      #define MYOBJECT_H

      #include <QtCore>

      class MyObject : public QObject
      {
      Q_OBJECT
      public:
      explicit MyObject(QObject *parent = 0);

      signals:

      public slots:
      void doWork();

      };

      #endif // MYOBJECT_H@

      main.cpp:

      @#include "mainwindow.h"
      #include <QApplication>

      int main(int argc, char *argv[])
      {
      QApplication a(argc, argv);
      MainWindow w;
      w.show();

      return a.exec&#40;&#41;;
      

      }@

      mainwindow.cpp:

      @#include "mainwindow.h"
      #include "ui_mainwindow.h"
      #include "myobject.h"

      MainWindow::MainWindow(QWidget *parent) :
      QMainWindow(parent),
      ui(new Ui::MainWindow)
      {
      ui->setupUi(this);

      QThread cThread;
      MyObject cObject;
      cObject.moveToThread(&cThread);
      
      QObject::connect(ui->pushButton, SIGNAL(clicked()), &cThread, SLOT(start()));
      QObject::connect(&cThread, SIGNAL(started()), &cObject, SLOT(doWork()));
      

      }

      MainWindow::~MainWindow()
      {
      delete ui;
      }@

      myobject.app:

      @#include "myobject.h"
      #include <QDebug>

      MyObject::MyObject(QObject *parent) :
      QObject(parent)
      {
      }

      void MyObject::doWork()
      {
      qDebug() << "1";
      }@

      I'm quite stumped. No errors. No output (should be gettting "1" from qDebug when clicking on the button). :|

      I can't see what's wrong.

      1 Reply Last reply Reply Quote 0
      • Chris Kawa
        Chris Kawa Moderators last edited by

        @
        {
        ui->setupUi(this);

        QThread cThread; //cThread is a local stack variable
        MyObject cObject; //cObject is a local stack variable
        cObject.moveToThread(&cThread);
        
        QObject::connect(ui->pushButton, SIGNAL(clicked()), &cThread, SLOT(start()));
        QObject::connect(&cThread, SIGNAL(started()), &cObject, SLOT(doWork()));
        

        } //here both cThread and cObject go out of scope, and thus are destroyed and disconnected from anything
        @
        You should create the thread and your object on the heap with a new keyword.

        1 Reply Last reply Reply Quote 0
        • T
          tahayassen last edited by

          Solution:

          @mainwindow.cpp:

          #include "mainwindow.h"
          #include "ui_mainwindow.h"
          #include "myobject.h"

          MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindow)
          {
          ui->setupUi(this);

          QThread *cThread = new QThread();
          MyObject *cObject = new MyObject();
          cObject->moveToThread(cThread);
          
          QObject::connect(ui->pushButton, SIGNAL(clicked()), cThread, SLOT(start()));
          QObject::connect(cThread, SIGNAL(started()), cObject, SLOT(doWork()));
          

          }

          MainWindow::~MainWindow()
          {
          delete ui;
          }@

          Wow. Thanks man! I really appreciate it.

          But now how do I prevent a memory leak? If they're on the heap, then doesn't that mean that I have to free the memory or something?

          1 Reply Last reply Reply Quote 0
          • Chris Kawa
            Chris Kawa Moderators last edited by

            Yup, you should delete it somewhere(lika in a destructor), or... do it the Qt way :)
            QObjects (like your thread) taka a parent parameter in their constructor. Set this to any other QObject (eg. your window) and it will be automagically deleted when the parent is.

            Alternatively, if you don't need the thread after its completion, you can do this:
            @
            MyObject *cObject = new MyObject(cThread); //make the object be destroyed with the thread
            connect(cThread, SIGNAL(finished()), cThread, SLOT(deleteLater()));
            @

            1 Reply Last reply Reply Quote 0
            • T
              tahayassen last edited by

              Thanks. Just would like to make sure that this is correct (this is the first way that you mentioned i.e. using parents):

              @QThread *cThread = new QThread(QMainWindow);
              MyObject *cObject = new MyObject(cThread);@

              Edit: Getting mainwindow.cpp:11: error: C2275: 'QMainWindow' : illegal use of this type as an expression

              Hmm... Not sure what I did wrong. :|

              Edit 2: Changed it to this and it's working now:

              @QThread *cThread = new QThread(this);
              MyObject *cObject = new MyObject(cThread);@

              Edit 3: Argh, now I'm getting this during runtime: QObject::moveToThread: Cannot move objects with a parent.

              Edit 4: Would it be ok if there are memory leaks? It's a small program anyways, so I don't want to waste your time.

              1 Reply Last reply Reply Quote 0
              • Chris Kawa
                Chris Kawa Moderators last edited by

                Ah, sorry. I should be sleeping a long time ago :P

                This should work:
                @
                QThread *cThread = new QThread(this);
                MyObject *cObject = new MyObject();
                cObject->moveToThread(cThread);

                QObject::connect(ui->pushButton, SIGNAL(clicked()), cThread, SLOT(start()));
                QObject::connect(cThread, SIGNAL(started()), cObject, SLOT(doWork()));
                
                QObject::connect(cThread, SIGNAL(finished()), cThread, SLOT(deleteLater()));
                QObject::connect(cThread, SIGNAL(finished()), cObject, SLOT(deleteLater()));
                

                @

                Or instead of that last connect you can manually schedule cObject for destruction in your doWork slot by calling deleteLater() there.

                Just remember that you should end your thread at some point otherwise it will spin around till the end of program and you will get a runtime warning: "QThread: Destroyed while thread is still running" and there will be no finished() signal so things won't get destroyed.
                You can do this for example in the doWork() slot by calling QThread::currentThread()->quit();

                As for "small memory leaks" - NO :) You will burn in programmers hell for saying such things ;)

                1 Reply Last reply Reply Quote 0
                • T
                  tahayassen last edited by

                  Works perfectly now. Thanks.

                  1 Reply Last reply Reply Quote 0
                  • T
                    tahayassen last edited by

                    https://mega.co.nz/#!xUMiSRYC!Y8Sxz2fEFb6yEIrnKiGx9n2zeK4YTUwUrCByaAkcOPI

                    So I've worked on the project a bit more and I'm experiencing a problem with QThread::currentThread()->quit();

                    If you open up my myobject.cpp and go to line 13, the quit() call is supposed to exit. But it seems the quit() call isn't working and it just skips it. Can't see the problem. :(

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post