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. Creating custom slots and signals

Creating custom slots and signals

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 4 Posters 5.2k 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.
  • F Offline
    F Offline
    Fuchsiaff
    wrote on last edited by Fuchsiaff
    #1

    Hi

    I have a worker thread and a main GUI. The worker thread reads values every 3 seconds.

    I want to emit that value to the main GUI every 3 seconds. How do I do that?

    I tried reading the documentation from qt5 but this is as far as I got:

    cpu_thread.h

    #ifndef CPU_THREAD_H
    #define CPU_THREAD_H
    #include <QThread>
    
    class cpu_thread : public QThread {
        Q_OBJECT
    public:
        cpu_thread();
        void run();
    public slots:
        void setValue(int value);
    
    signals:
        void valueChanged(int value);
    };
    
    #endif // CPU_THREAD_H
    

    cpu_thread.cpp

    #include "cpu_thread.h"
    #include <QDebug>
    #include <QProcess>
    #include <QTest>
    
    cpu_thread::cpu_thread() {
    
    }
    
    void cpu_thread::run() {
        while (true) {
    
            QThread *thread = new QThread;
            QProcess *process = new QProcess;
            process->moveToThread(thread);
            process->start("cat /proc/loadavg");
            process->waitForFinished(-1);
    
            QString stdout = process->readAllStandardOutput().trimmed();
            stdout.truncate(4);
            qDebug() << stdout;
    
            QTest::qWait(3000);
        }
    }
    
    void cpu_thread::setValue(int value) {
    
        emit valueChanged(value);
    }
    

    Now the main gui which is supposed to capture the value and update the gui looks like this:

    #include "ui_mainwindow.h"
    #include <QProcess>
    #include <QDebug>
    #include <QThread>
    #include <cpu_thread.h>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow) {
        ui->setupUi(this);
        cpu_thread *my_thread = new cpu_thread;
        my_thread->start();
        cores = getCpuCores();
    
    }
    
    MainWindow::~MainWindow() {
        delete ui;
    }
    
    void MainWindow::on_actionExit_triggered() {
        qApp->exit();
    }
    
    void MainWindow::mousePressEvent(QMouseEvent *event) {
        m_nMouseClick_X_Coordinate = event->x();
        m_nMouseClick_Y_Coordinate = event->y();
    }
    
    void MainWindow::mouseMoveEvent(QMouseEvent *event) {
        move(event->globalX()-m_nMouseClick_X_Coordinate,event->globalY()-m_nMouseClick_Y_Coordinate);
    }
    
    int MainWindow::getCpuCores() {
    
        QProcess *process = new QProcess;
    
        process->start("nproc");
        process->waitForFinished(-1);
    
        QString stdout = process->readAllStandardOutput().trimmed();
        QString stderr = process->readAllStandardError().trimmed();
    
        int cores = stdout.toInt();
    
        return cores/2;
    }
    
    void MainWindow::test() {
    
        QThread *thread = new QThread;
        QProcess *process = new QProcess;
        process->moveToThread(thread);
        process->start("cat /proc/loadavg");
        process->waitForFinished(-1);
    
        QString stdout = process->readAllStandardOutput().trimmed();
        qDebug() << stdout;
    
    }
    
    void MainWindow::updateCpu(QString value) {
    
        ui->lcdNumber->display(value);
    }```
    sierdzioS 1 Reply Last reply
    0
    • F Fuchsiaff

      Hi

      I have a worker thread and a main GUI. The worker thread reads values every 3 seconds.

      I want to emit that value to the main GUI every 3 seconds. How do I do that?

      I tried reading the documentation from qt5 but this is as far as I got:

      cpu_thread.h

      #ifndef CPU_THREAD_H
      #define CPU_THREAD_H
      #include <QThread>
      
      class cpu_thread : public QThread {
          Q_OBJECT
      public:
          cpu_thread();
          void run();
      public slots:
          void setValue(int value);
      
      signals:
          void valueChanged(int value);
      };
      
      #endif // CPU_THREAD_H
      

      cpu_thread.cpp

      #include "cpu_thread.h"
      #include <QDebug>
      #include <QProcess>
      #include <QTest>
      
      cpu_thread::cpu_thread() {
      
      }
      
      void cpu_thread::run() {
          while (true) {
      
              QThread *thread = new QThread;
              QProcess *process = new QProcess;
              process->moveToThread(thread);
              process->start("cat /proc/loadavg");
              process->waitForFinished(-1);
      
              QString stdout = process->readAllStandardOutput().trimmed();
              stdout.truncate(4);
              qDebug() << stdout;
      
              QTest::qWait(3000);
          }
      }
      
      void cpu_thread::setValue(int value) {
      
          emit valueChanged(value);
      }
      

      Now the main gui which is supposed to capture the value and update the gui looks like this:

      #include "ui_mainwindow.h"
      #include <QProcess>
      #include <QDebug>
      #include <QThread>
      #include <cpu_thread.h>
      
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindow) {
          ui->setupUi(this);
          cpu_thread *my_thread = new cpu_thread;
          my_thread->start();
          cores = getCpuCores();
      
      }
      
      MainWindow::~MainWindow() {
          delete ui;
      }
      
      void MainWindow::on_actionExit_triggered() {
          qApp->exit();
      }
      
      void MainWindow::mousePressEvent(QMouseEvent *event) {
          m_nMouseClick_X_Coordinate = event->x();
          m_nMouseClick_Y_Coordinate = event->y();
      }
      
      void MainWindow::mouseMoveEvent(QMouseEvent *event) {
          move(event->globalX()-m_nMouseClick_X_Coordinate,event->globalY()-m_nMouseClick_Y_Coordinate);
      }
      
      int MainWindow::getCpuCores() {
      
          QProcess *process = new QProcess;
      
          process->start("nproc");
          process->waitForFinished(-1);
      
          QString stdout = process->readAllStandardOutput().trimmed();
          QString stderr = process->readAllStandardError().trimmed();
      
          int cores = stdout.toInt();
      
          return cores/2;
      }
      
      void MainWindow::test() {
      
          QThread *thread = new QThread;
          QProcess *process = new QProcess;
          process->moveToThread(thread);
          process->start("cat /proc/loadavg");
          process->waitForFinished(-1);
      
          QString stdout = process->readAllStandardOutput().trimmed();
          qDebug() << stdout;
      
      }
      
      void MainWindow::updateCpu(QString value) {
      
          ui->lcdNumber->display(value);
      }```
      sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      @Fuchsiaff said in Creating custom slots and signals:

      cpu_thread *my_thread = new cpu_thread;
      connect(my_therad, &cpu_thread::valueChanged, this, &MainWindow::someSlotYouCreateInMainWindow);
      my_thread->start()
      

      That should do it on UI side. In your thread, you need to emit the value, that would probably look like:

      qDebug() << stdout; // BTW that's a HORRIBLE variable name!
      emit valueChanged(stdout.toInt());
      QTest::qWait(3000);
      

      But, and that is a BIG but - your code is overdoing it massively.

      You don't need a thread. QProcess already runs in a separate process - it won't block your UI at all! So you can simplify all this like so:

      • remove whole cpu_thread class
      • in MainWindow do this:
      QTimer *timer = new QTimer(this);
      timer->setInterval(3000);
      timer->setSingleShot(false);
      // Using a lambda, but you can (should) create your own slot for this, of course
      connect(timer, &QTimer::timeout, this, [this] {
        QProcess *process = new QProcess(this);
        process->start("cat /proc/loadavg");
        connect(process, &QProcess::finished, this, &MainWindow::someSlot);
      });
      
      // Your slot:
      void MainWindow::someSlot() {
        QProcess *process = qobject_cast<QProcess *>(sender());
        ui->lcdNumber->display(process->readAllStandardOutput());
        process->deleteLater();
      }
      

      Brain to terminal, not tested of course. But it should give you a general idea.

      (Z(:^

      1 Reply Last reply
      3
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by SGaist
        #3

        Hi,

        Rather than calling cat, why not just use a QFile and read the content of /proc/loadavg ?

        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
        5
        • F Offline
          F Offline
          Fuchsiaff
          wrote on last edited by
          #4

          Anyway, after using code suggested by sierdzo,

          mainwindow.cpp

          MainWindow::MainWindow(QWidget *parent) :
              QMainWindow(parent),
              ui(new Ui::MainWindow) {
              ui->setupUi(this);
              QTimer *timer = new QTimer(this);
              timer->setInterval(3000);
              timer->setSingleShot(false);
              // Using a lambda, but you can (should) create your own slot for this, of course
              QObject::connect(timer, &QTimer::timeout, this, [this] {
                QProcess *process = new QProcess(this);
                process->start("cat /proc/loadavg");
                QObject::connect(process, &QProcess::finished, this, &MainWindow::updateCpu);
              });
              cores = getCpuCores();
          
          }
          
          void MainWindow::updateCpu(int exitCode, QProcess::ExitStatus exitStatus) {
          
              QProcess *process = qobject_cast<QProcess *>(sender());
              QString result = process->readAllStandardOutput().trimmed();
              result.truncate(4);
              ui->lcdNumber->display(result);
              process->deleteLater();
          }
          

          mainwindow.h

          #ifndef MAINWINDOW_H
          #define MAINWINDOW_H
          
          #include <QMouseEvent>
          #include <QMainWindow>
          #include <QProcess>
          
          namespace Ui {
          class MainWindow;
          }
          
          class MainWindow : public QMainWindow {
              Q_OBJECT
          
          public:
              explicit MainWindow(QWidget *parent = nullptr);
              int getCpuCores();
              void updateCpu(int exitCode, QProcess::ExitStatus exitStatus);
              void updateRAM(QString value);
              void updateNetwork(QString value);
              void updateFanSpeed(QString value);
              int cores;
              ~MainWindow();
          
          private slots:
              void on_actionExit_triggered();
          
          private:
              void mousePressEvent(QMouseEvent *event);
              void mouseMoveEvent(QMouseEvent *event);
              int m_nMouseClick_X_Coordinate;
              int m_nMouseClick_Y_Coordinate;
              Ui::MainWindow *ui;
              bool isMouseDown = false;
          
          };
          
          #endif // MAINWINDOW_H
          

          Qtcreator shows me this:
          alt text

          No matching function call for call to "connect"

          1 Reply Last reply
          0
          • sierdzioS Offline
            sierdzioS Offline
            sierdzio
            Moderators
            wrote on last edited by
            #5

            Hint from @SGaist is far better :-)

            No matching function call for call to "connect"

            Which connect? QtC will show you exactly the line where compilation failed.

            (Z(:^

            1 Reply Last reply
            0
            • F Offline
              F Offline
              Fuchsiaff
              wrote on last edited by
              #6

              This part:

               QObject::connect(process, &QProcess::finished, this, &MainWindow::updateCpu);
              
              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                What is the exact error ?

                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
                • F Offline
                  F Offline
                  Fuchsiaff
                  wrote on last edited by
                  #8

                  /home/bot/Hardware_mon/mainwindow.cpp:19: error: no matching function for call to ‘MainWindow::connect(QProcess*&, <unresolved overloaded function type>, MainWindow*, void (MainWindow::*)(int, QProcess::ExitStatus))’ QObject::connect(process, &QProcess::finished, this, &MainWindow::updateCpu); ^

                  1 Reply Last reply
                  0
                  • sierdzioS Offline
                    sierdzioS Offline
                    sierdzio
                    Moderators
                    wrote on last edited by
                    #9

                    The documentation has the proper code for this connect.

                    (Z(:^

                    1 Reply Last reply
                    0
                    • F Offline
                      F Offline
                      Fuchsiaff
                      wrote on last edited by
                      #10

                      So something like this?

                      connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                          [=](int exitCode, QProcess::ExitStatus exitStatus){ 
                           QProcess *process = new QProcess(this);
                            process->start("cat /proc/loadavg");
                            QObject::connect(process, &QProcess::finished, this, &MainWindow::updateCpu);
                            
                       });
                      

                      that connect looks even more confusing, i'm even more lost now

                      aha_1980A 1 Reply Last reply
                      0
                      • F Fuchsiaff

                        So something like this?

                        connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                            [=](int exitCode, QProcess::ExitStatus exitStatus){ 
                             QProcess *process = new QProcess(this);
                              process->start("cat /proc/loadavg");
                              QObject::connect(process, &QProcess::finished, this, &MainWindow::updateCpu);
                              
                         });
                        

                        that connect looks even more confusing, i'm even more lost now

                        aha_1980A Offline
                        aha_1980A Offline
                        aha_1980
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Hi @Fuchsiaff: Then try this:

                        QByteArray avg;
                        QFile f("/proc/loadavg");
                        if (f.open(QIODevice::ReadOnly)) {
                          avg = f.readAll();
                          f.close();
                        }
                        // avg now contains the content of /proc/loadavg
                        

                        Qt has to stay free or it will die.

                        1 Reply Last reply
                        1
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished)

                          reads as: use the overloaded version of finished having the matching signature: QProcess::finished(int, QProcess::ExitStatus)

                          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
                          1
                          • F Offline
                            F Offline
                            Fuchsiaff
                            wrote on last edited by
                            #13

                            I got it to compile with this code

                            MainWindow::MainWindow(QWidget *parent) :
                                QMainWindow(parent),
                                ui(new Ui::MainWindow) {
                                ui->setupUi(this);
                                QTimer *timer = new QTimer(this);
                                timer->setInterval(3000);
                                timer->setSingleShot(false);
                                // Using a lambda, but you can (should) create your own slot for this, of course
                                QObject::connect(timer, &QTimer::timeout, this, [this] {
                                  QProcess *process = new QProcess(this);
                                  process->start("cat /proc/loadavg");
                                  qDebug() << "hi";
                                  QObject::connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(updateCpu(int, QProcess::ExitStatus)));
                                });
                                cores = getCpuCores();
                            
                            }
                            
                            

                            But now, looking at the application output section, the string "hi" isn't printed so i'm quessing the timer never reached the timeout signal, but why?

                            1 Reply Last reply
                            0
                            • SGaistS Offline
                              SGaistS Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on last edited by SGaist
                              #14

                              From the code you posted, you don't start timer.

                              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
                              4

                              • Login

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