Qt Forum

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

    Unsolved Creating custom slots and signals

    General and Desktop
    4
    14
    4316
    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.
    • F
      Fuchsiaff last edited by 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);
      }```
      sierdzio 1 Reply Last reply Reply Quote 0
      • sierdzio
        sierdzio Moderators @Fuchsiaff last edited by

        @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 Reply Quote 3
        • SGaist
          SGaist Lifetime Qt Champion last edited by SGaist

          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 Reply Quote 5
          • F
            Fuchsiaff last edited by

            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:

            No matching function call for call to "connect"

            1 Reply Last reply Reply Quote 0
            • sierdzio
              sierdzio Moderators last edited by

              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 Reply Quote 0
              • F
                Fuchsiaff last edited by

                This part:

                 QObject::connect(process, &QProcess::finished, this, &MainWindow::updateCpu);
                
                1 Reply Last reply Reply Quote 0
                • SGaist
                  SGaist Lifetime Qt Champion last edited by

                  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 Reply Quote 0
                  • F
                    Fuchsiaff last edited by

                    /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 Reply Quote 0
                    • sierdzio
                      sierdzio Moderators last edited by

                      The documentation has the proper code for this connect.

                      (Z(:^

                      1 Reply Last reply Reply Quote 0
                      • F
                        Fuchsiaff last edited by

                        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_1980 1 Reply Last reply Reply Quote 0
                        • aha_1980
                          aha_1980 Lifetime Qt Champion @Fuchsiaff last edited by

                          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 Reply Quote 1
                          • SGaist
                            SGaist Lifetime Qt Champion last edited by

                            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 Reply Quote 1
                            • F
                              Fuchsiaff last edited by

                              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 Reply Quote 0
                              • SGaist
                                SGaist Lifetime Qt Champion last edited by SGaist

                                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 Reply Quote 4
                                • First post
                                  Last post