Results 1 to 20 of 20

Thread: How to connect signal-slog in second thread?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default How to connect signal-slog in second thread?

    Hi everyone.

    I'm working on a little desktop gui app, which starts some other thread which would watch for changes in a certain file. I know I don't need a second thread for this, but would really like to, since I would do some time consuming processing on that file change event and would like to keep my main thread where gui app resides, still responsive to user comands.

    Ok, so I have my second thread, but the problem is, that I can not connect signal-slot in it. The message I get at run time is "QObject::connect: No such slot QThread::HandleFileChange(const QString)". The relevant part of the code is bellow. Much thanks for help.

    worker.h
    Qt Code:
    1. #ifndef WORKER_H
    2. #define WORKER_H
    3. #include <QThread>
    4. #include <QFileSystemWatcher>
    5.  
    6. class Worker: public QThread
    7. {
    8. public:
    9. Worker(QString SrcFileParam,QString WorkerFolderParam);
    10.  
    11. void run();
    12.  
    13. private:
    14. QString SrcFilename,WorkerFolder;
    15. int Cntr;
    16. QFileSystemWatcher * watcher;
    17.  
    18. public slots:
    19. void HandleFileChange(const QString fileName);
    20.  
    21. };
    22.  
    23. #endif // WORKER_H
    To copy to clipboard, switch view to plain text mode 

    worker.cpp
    Qt Code:
    1. #include "Worker.h"
    2. #include <iostream>
    3. #include <QMessageBox>
    4. #include <QFile>
    5. #include <QFileInfo>
    6.  
    7. Worker::Worker(QString SrcFileParam,QString WorkerFolderParam)
    8. {
    9. SrcFilename = SrcFileParam;
    10. WorkerFolder = WorkerFolderParam;
    11.  
    12. watcher = new QFileSystemWatcher(this);
    13. watcher->addPath(this->SrcFilename);
    14.  
    15. }
    16.  
    17. void Worker::run() {
    18. connect(watcher,SIGNAL(fileChanged(QString)),this,SLOT(HandleFileChange(const QString))); //problematical line
    19. for (int i=1;i<100;i++) {
    20. //std::cout << qPrintable(i);
    21. //std::cout << "printed from Worker class \nl";
    22. //QMessageBox::information(0,tr("Info"),QString::number(i));
    23. }
    24.  
    25. }
    26.  
    27. void Worker::HandleFileChange(const QString fileName) {
    28. // some code
    29. }
    To copy to clipboard, switch view to plain text mode 

    mainwindow.cpp
    Qt Code:
    1. Worker wkr1(ui->lineEdit->text(),ui->lineEdit_2->text());
    2. wkr1.start();
    3. wkr1.wait();
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jun 2015
    Location
    India
    Posts
    185
    Thanks
    8
    Thanked 14 Times in 14 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to connect signal-slog in second thread?

    signal is fileChanged ( const QString &) not fileChanged (QString)
    and you need to add Q_OBJECT marco in worker class.

    one more thing is, if we use signal/slot across threads we need to start local event loop with exec() at the end of the run function;
    Thanks :-)

  3. #3
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to connect signal-slog in second thread?

    Thanks prasad_N, but
    Quote Originally Posted by prasad_N View Post
    signal is fileChanged ( const QString &) not fileChanged (QString)
    according to codecompletion that is not true.
    and you need to add Q_OBJECT marco in worker class.
    would you please show a short sample how to do it, remember a newbie
    one more thing is, if we use signal/slot across threads we need to start local event loop with exec() at the end of the run function;
    I'm not sure I understand this one,should I put exec() in main thread or inside Worker::run. If you can add adjustments to my case I would be really gratefull, much thanks again.

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to connect signal-slog in second thread?

    Quote Originally Posted by arcull View Post
    according to codecompletion that is not true
    Correct, just QString is the simplified/normalized argument type signature.

    Quote Originally Posted by arcull View Post
    would you please show a short sample how to do it, remember a newbie
    Q_OBJECT is placed right after the opening brace { of the class declaration

    Qt Code:
    1. class MyClass : public QObject
    2. {
    3. Q_OBJECT
    4. };
    To copy to clipboard, switch view to plain text mode 

    Quote Originally Posted by arcull View Post
    I'm not sure I understand this one,should I put exec() in main thread or inside Worker::run. If you can add adjustments to my case I would be really gratefull, much thanks again.
    You only need event loop on the thread that receives the signals. In your case that is the main thread.
    The instance of Worker is created by the main thread, thus the slot HandleFileChange(QString) will be executed in the main thread.
    The signal source, in this case the file system watcher, is also in the main thread, so its events are also handled there.

    The only thing the worker thread does in this example is running a for loop and then exit.

    Cheers,
    _

  5. #5
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to connect signal-slog in second thread?

    Quote Originally Posted by anda_skoa View Post
    Correct, just QString is the simplified/normalized argument type signature.


    Q_OBJECT is placed right after the opening brace { of the class declaration

    Qt Code:
    1. class MyClass : public QObject
    2. {
    3. Q_OBJECT
    4. };
    To copy to clipboard, switch view to plain text mode 



    You only need event loop on the thread that receives the signals. In your case that is the main thread.
    The instance of Worker is created by the main thread, thus the slot HandleFileChange(QString) will be executed in the main thread.
    The signal source, in this case the file system watcher, is also in the main thread, so its events are also handled there.

    The only thing the worker thread does in this example is running a for loop and then exit.

    Cheers,
    _
    Thanks. You are right, that is how it would work now. But I would like the second thread (Worker class) to receive the signals and connect them to correct slot, ie. I would like the watching and handling file changes to be done by the second thread. How could I accieve this? Besides, what would I put in the run method of Worker class in this case, because I need it to "keep alive" and not exit if that is not requested from the main thread. Would an infinite loop be ok? Please suggest, a short snippet of code would be great. Thanks for your help.

  6. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to connect signal-slog in second thread?

    There are three options:

    1) treat your run() method like you would treat the main() function, i.e. forget about the encapsulating object.
    Just create an instance of the actual worker object and call exec() on the thread.

    2) Use the moveToThread approach: create an instance of a QObject derived worker class and an instance of plain QThread and call worker->moveToThread(threadInstance)

    3) Create the file system watcher in run() instead of your thread class' constructor and use Qt:irectConnection when connecting to the slot in your thread class.
    Call exec() at the end of run()

    Cheers,
    _

  7. #7
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to connect signal-slog in second thread?

    Thanks anda_skoa.
    1) treat your run() method like you would treat the main() function, i.e. forget about the encapsulating object.
    Just create an instance of the actual worker object and call exec() on the thread.
    This one sounds the easiest So in my case, run() method of Worker class would have just one line of code to connect signal slot? After calling exec() on the thread, will the thread stay alive, that is, would it handle signal slot events? Am I still able to terminate this thread from the first one? Thanks again.

  8. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,316
    Thanks
    315
    Thanked 870 Times in 857 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to connect signal-slog in second thread?

    Maybe reading some of the Qt threading examples and tutorials would help you.

  9. #9
    Join Date
    Jun 2015
    Location
    India
    Posts
    185
    Thanks
    8
    Thanked 14 Times in 14 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to connect signal-slog in second thread?

    Thanks :-)

  10. #10
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Red face Re: How to connect signal-slog in second thread?

    Ok, I've solved it with a bit of trial and error. Here is a working sample:
    mainwindow.cpp
    Qt Code:
    1. Worker *wrkr1;
    2. wrkr1 = new Worker(ui->lineEdit->text(),ui->lineEdit_2->text());
    3. wrkr1->start();
    To copy to clipboard, switch view to plain text mode 
    workder.h
    Qt Code:
    1. #ifndef WORKER_H
    2. #define WORKER_H
    3. #include <QThread>
    4. #include <QFileSystemWatcher>
    5. #include <QObject>
    6.  
    7. class Worker: public QThread
    8. {
    9. Q_OBJECT
    10.  
    11. public:
    12. Worker(QString SrcFileParam,QString WorkerFolderParam);
    13.  
    14. void run();
    15.  
    16. private:
    17. QString SrcFilename,WorkerFolder;
    18. int Cntr;
    19. QFileSystemWatcher * watcher;
    20.  
    21. public slots:
    22. void HandleFileChange(const QString fileName);
    23.  
    24. };
    25.  
    26. #endif // WORKER_H
    To copy to clipboard, switch view to plain text mode 
    worker.cpp
    Qt Code:
    1. #include "Worker.h"
    2. #include <iostream>
    3. #include <QMessageBox>
    4. #include <QFile>
    5. #include <QFileInfo>
    6.  
    7. Worker::Worker(QString SrcFileParam,QString WorkerFolderParam)
    8. {
    9. std::cout << "Worker constructor \n";
    10. SrcFilename = SrcFileParam;
    11. WorkerFolder = WorkerFolderParam;
    12.  
    13. watcher = new QFileSystemWatcher();
    14. watcher->addPath(this->SrcFilename);
    15.  
    16. }
    17.  
    18. void Worker::run() {
    19. connect(watcher,SIGNAL(fileChanged(QString)),this,SLOT(HandleFileChange(const QString)));
    20. qDebug("method run in Worker thread");
    21. exec();
    22. }
    23.  
    24. void Worker::HandleFileChange(const QString fileName) {
    25. qDebug("HandleFileChange triggered...");
    26. //some code
    27. }
    To copy to clipboard, switch view to plain text mode 
    To sum up, I've made 3 crucial mistakes:
    1)forgetting Q_OBJECT macro, without it the Worker thread wont have signal/slot functionality
    2)starting the second thread and then waiting.
    3)missing exec() in my Worker thread

    Now it works,I'm happy. Thank you all for help.

  11. #11
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to connect signal-slog in second thread?

    Quote Originally Posted by arcull View Post
    So in my case, run() method of Worker class would have just one line of code to connect signal slot?
    No.
    As I wrote, this approach treats run() like main().
    There is no slot to connect to unless you create an object that has such a slot.

    Quote Originally Posted by arcull View Post
    After calling exec() on the thread, will the thread stay alive, that is, would it handle signal slot events?
    Yes.

    Quote Originally Posted by arcull View Post
    Am I still able to terminate this thread from the first one?
    Yes, simply by calling the thread's quit() method.

    Quote Originally Posted by arcull View Post
    Ok, I've solved it with a bit of trial and error. Here is a working sample:
    No.
    That still processes everything in the main thread.
    Your worker thread does nothing, it jus sits there waiting for events that never come.

    Cheers,
    _

Similar Threads

  1. How to connect signal to signal in QWidget correctly
    By Mint87 in forum Qt Programming
    Replies: 2
    Last Post: 6th February 2013, 00:06
  2. Replies: 5
    Last Post: 13th November 2012, 12:43
  3. Connect signal/signal in Qt Designer
    By jlemaitre in forum Newbie
    Replies: 1
    Last Post: 22nd September 2010, 15:53
  4. Replies: 5
    Last Post: 16th January 2010, 09:17
  5. Replies: 9
    Last Post: 28th November 2009, 20:31

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.