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. QT Signals And Slots Between 2 Classes
Qt 6.11 is out! See what's new in the release blog

QT Signals And Slots Between 2 Classes

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 4 Posters 963 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.
  • J Offline
    J Offline
    JPatrick
    wrote on last edited by
    #1

    From what I've understood, I should be very close in my code. I've got two separate Q_OBJECT objects housed under my main program class, but when it comes time to connect the Signal to the Slot I run into an issue.

    The UIGraph object has a button, Recalculate, which when clicked will emit the signal CreateNewRun. I want this to trigger a function in the PID object which will execute some code.

    Optimally, I'll have the PID object then emit a signal afterwards to tell the UI to update based on the code available or pass a reference through the signal of the new code to be plotted. I feel like I'm missing something simple here. Any thoughts?

    Code below:

    mainwindow.cpp

    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // UI Component
        graph = new UIGraph(this);
        QWidget* graphObject = graph->SetupUI();
    
        // PID Component
        pid = new PIDFunction();
        // Neither of these successfully resolve
        connect(&graph, SIGNAL(CreateNewRun()), this->pid, SLOT(GenerateNewRun()));
        connect(&graph, &UIGraph::CreateNewRun, &pid, &PIDFunction::GenerateNewRun);
    
        setCentralWidget(graphObject);
    }
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include "UI/uigraph.h"
    #include "PID/pidfunction.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
        UIGraph *graph;
        PIDFunction *pid;
    };
    #endif // MAINWINDOW_H
    

    UIGraph.h

    #ifndef UIGRAPH_H
    #define UIGRAPH_H
    
    #include <QWidget>
    #include <QMainWindow>
    #include <QGroupBox>
    #include <QLabel>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QVBoxLayout>
    #include <QComboBox>
    #include "qcustomplot.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    enum TextIndications{
        ProprtionalGain,
        IntegralGain,
        DerivativeGain,
        LoopInterval,
        TargetValue,
        Period,
        Recalculate
    };
    
    class UIGraph : public QWidget
    {
        Q_OBJECT
    public:
        UIGraph(QWidget *parent = nullptr);
        void GenerateNewData();
        QWidget* SetupUI();
    
    signals:
        void CreateNewRun();
    
    private:
        Ui::MainWindow *ui;
        void PlotSetup();
        void SetupControlColumn();
        void PressRecalculateButton();
    
        QGroupBox *gridGroupBox;
        QLabel *labels[6];
        QLineEdit *lineEdits[6];
        QPushButton *recalculate;
        QVBoxLayout *mainLayout;
        QGridLayout *layout;
        QCustomPlot *customPlot;
        QComboBox *signalStyle;
        QWidget *body;
    
    //private slots:
    //    void GenerateNewGraph();
    
    signals:
    
    };
    
    #endif // UIGRAPH_H
    

    pidfunction.h

    #ifndef PIDFUNCTION_H
    #define PIDFUNCTION_H
    
    #include "functiongenerator.h"
    #include <QObject>
    
    enum FunctionType {_line, _sin, _saw, _triangle, _square, _curvTriCave, _curTriVex };
    
    class PIDFunction : public FunctionGenerator, public QObject
    {
        Q_OBJECT
    
    public:
        PIDFunction();
        void GenerateNextPoint();
        QVector<double> yOutput;
        void Process(double val);
        double Calculate(double setpoint, double pv);
    
        void SetP(double p);
        void SetI(double i);
        void SetD(double d);
        void SetLoopInterval(int _dt);
        void SetTargetValue(double t);
        //void SetPeriod(int p);
    
        void SetWaveform(int);
    
        void Reset();
    
    public slots:
        void GenerateNewRun();
    
    private:
        // proportional, integral, derivative
        double kp, ki, kd;
        // loop interval time
        double dt;
        // Min/Max of manipulated variable
        double max, min;
        // integral
        double integral;
        // Previous Error
        double pre_error = 0;
        // Stored Error
        double storedError = 0;
        // Target Value
        double target = 0;
        // Period
        int period = 10;
    
        double previousError;
    
        FunctionType ft;
    };
    
    #endif // PIDFUNCTION_H
    
    JonBJ KroMignonK 2 Replies Last reply
    0
    • Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Conect the signal and slot where you have access to both classes.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      2
      • J JPatrick

        From what I've understood, I should be very close in my code. I've got two separate Q_OBJECT objects housed under my main program class, but when it comes time to connect the Signal to the Slot I run into an issue.

        The UIGraph object has a button, Recalculate, which when clicked will emit the signal CreateNewRun. I want this to trigger a function in the PID object which will execute some code.

        Optimally, I'll have the PID object then emit a signal afterwards to tell the UI to update based on the code available or pass a reference through the signal of the new code to be plotted. I feel like I'm missing something simple here. Any thoughts?

        Code below:

        mainwindow.cpp

        MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
        
            // UI Component
            graph = new UIGraph(this);
            QWidget* graphObject = graph->SetupUI();
        
            // PID Component
            pid = new PIDFunction();
            // Neither of these successfully resolve
            connect(&graph, SIGNAL(CreateNewRun()), this->pid, SLOT(GenerateNewRun()));
            connect(&graph, &UIGraph::CreateNewRun, &pid, &PIDFunction::GenerateNewRun);
        
            setCentralWidget(graphObject);
        }
        

        mainwindow.h

        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H
        
        #include <QMainWindow>
        #include "UI/uigraph.h"
        #include "PID/pidfunction.h"
        
        QT_BEGIN_NAMESPACE
        namespace Ui { class MainWindow; }
        QT_END_NAMESPACE
        
        class MainWindow : public QMainWindow
        {
            Q_OBJECT
        
        public:
            MainWindow(QWidget *parent = nullptr);
            ~MainWindow();
        
        private:
            Ui::MainWindow *ui;
            UIGraph *graph;
            PIDFunction *pid;
        };
        #endif // MAINWINDOW_H
        

        UIGraph.h

        #ifndef UIGRAPH_H
        #define UIGRAPH_H
        
        #include <QWidget>
        #include <QMainWindow>
        #include <QGroupBox>
        #include <QLabel>
        #include <QLineEdit>
        #include <QPushButton>
        #include <QVBoxLayout>
        #include <QComboBox>
        #include "qcustomplot.h"
        
        QT_BEGIN_NAMESPACE
        namespace Ui { class MainWindow; }
        QT_END_NAMESPACE
        
        enum TextIndications{
            ProprtionalGain,
            IntegralGain,
            DerivativeGain,
            LoopInterval,
            TargetValue,
            Period,
            Recalculate
        };
        
        class UIGraph : public QWidget
        {
            Q_OBJECT
        public:
            UIGraph(QWidget *parent = nullptr);
            void GenerateNewData();
            QWidget* SetupUI();
        
        signals:
            void CreateNewRun();
        
        private:
            Ui::MainWindow *ui;
            void PlotSetup();
            void SetupControlColumn();
            void PressRecalculateButton();
        
            QGroupBox *gridGroupBox;
            QLabel *labels[6];
            QLineEdit *lineEdits[6];
            QPushButton *recalculate;
            QVBoxLayout *mainLayout;
            QGridLayout *layout;
            QCustomPlot *customPlot;
            QComboBox *signalStyle;
            QWidget *body;
        
        //private slots:
        //    void GenerateNewGraph();
        
        signals:
        
        };
        
        #endif // UIGRAPH_H
        

        pidfunction.h

        #ifndef PIDFUNCTION_H
        #define PIDFUNCTION_H
        
        #include "functiongenerator.h"
        #include <QObject>
        
        enum FunctionType {_line, _sin, _saw, _triangle, _square, _curvTriCave, _curTriVex };
        
        class PIDFunction : public FunctionGenerator, public QObject
        {
            Q_OBJECT
        
        public:
            PIDFunction();
            void GenerateNextPoint();
            QVector<double> yOutput;
            void Process(double val);
            double Calculate(double setpoint, double pv);
        
            void SetP(double p);
            void SetI(double i);
            void SetD(double d);
            void SetLoopInterval(int _dt);
            void SetTargetValue(double t);
            //void SetPeriod(int p);
        
            void SetWaveform(int);
        
            void Reset();
        
        public slots:
            void GenerateNewRun();
        
        private:
            // proportional, integral, derivative
            double kp, ki, kd;
            // loop interval time
            double dt;
            // Min/Max of manipulated variable
            double max, min;
            // integral
            double integral;
            // Previous Error
            double pre_error = 0;
            // Stored Error
            double storedError = 0;
            // Target Value
            double target = 0;
            // Period
            int period = 10;
        
            double previousError;
        
            FunctionType ft;
        };
        
        #endif // PIDFUNCTION_H
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @JPatrick said in QT Signals And Slots Between 2 Classes:

        // Neither of these successfully resolve
        connect(&graph, SIGNAL(CreateNewRun()), this->pid, SLOT(GenerateNewRun()));
        connect(&graph, &UIGraph::CreateNewRun, &pid, &PIDFunction::GenerateNewRun);
        

        Hi and welcome.

        If you showed/looked at the error message you would get further.

        Get rid of the SIGNAL/SLOT() macros approach and stick to the second case new style for all your work. There the error message should be telling you (read it carefully!) what is wrong with your parameter types. (Hint: &graph and &pid are wrong, you're almost there but over-complicating....)

        J 1 Reply Last reply
        2
        • Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Was this connect really there when I read it the first time? Strange...
          Take a look at https://doc.qt.io/qt-5/signalsandslots.html

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          0
          • J JPatrick

            From what I've understood, I should be very close in my code. I've got two separate Q_OBJECT objects housed under my main program class, but when it comes time to connect the Signal to the Slot I run into an issue.

            The UIGraph object has a button, Recalculate, which when clicked will emit the signal CreateNewRun. I want this to trigger a function in the PID object which will execute some code.

            Optimally, I'll have the PID object then emit a signal afterwards to tell the UI to update based on the code available or pass a reference through the signal of the new code to be plotted. I feel like I'm missing something simple here. Any thoughts?

            Code below:

            mainwindow.cpp

            MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
            {
                ui->setupUi(this);
            
                // UI Component
                graph = new UIGraph(this);
                QWidget* graphObject = graph->SetupUI();
            
                // PID Component
                pid = new PIDFunction();
                // Neither of these successfully resolve
                connect(&graph, SIGNAL(CreateNewRun()), this->pid, SLOT(GenerateNewRun()));
                connect(&graph, &UIGraph::CreateNewRun, &pid, &PIDFunction::GenerateNewRun);
            
                setCentralWidget(graphObject);
            }
            

            mainwindow.h

            #ifndef MAINWINDOW_H
            #define MAINWINDOW_H
            
            #include <QMainWindow>
            #include "UI/uigraph.h"
            #include "PID/pidfunction.h"
            
            QT_BEGIN_NAMESPACE
            namespace Ui { class MainWindow; }
            QT_END_NAMESPACE
            
            class MainWindow : public QMainWindow
            {
                Q_OBJECT
            
            public:
                MainWindow(QWidget *parent = nullptr);
                ~MainWindow();
            
            private:
                Ui::MainWindow *ui;
                UIGraph *graph;
                PIDFunction *pid;
            };
            #endif // MAINWINDOW_H
            

            UIGraph.h

            #ifndef UIGRAPH_H
            #define UIGRAPH_H
            
            #include <QWidget>
            #include <QMainWindow>
            #include <QGroupBox>
            #include <QLabel>
            #include <QLineEdit>
            #include <QPushButton>
            #include <QVBoxLayout>
            #include <QComboBox>
            #include "qcustomplot.h"
            
            QT_BEGIN_NAMESPACE
            namespace Ui { class MainWindow; }
            QT_END_NAMESPACE
            
            enum TextIndications{
                ProprtionalGain,
                IntegralGain,
                DerivativeGain,
                LoopInterval,
                TargetValue,
                Period,
                Recalculate
            };
            
            class UIGraph : public QWidget
            {
                Q_OBJECT
            public:
                UIGraph(QWidget *parent = nullptr);
                void GenerateNewData();
                QWidget* SetupUI();
            
            signals:
                void CreateNewRun();
            
            private:
                Ui::MainWindow *ui;
                void PlotSetup();
                void SetupControlColumn();
                void PressRecalculateButton();
            
                QGroupBox *gridGroupBox;
                QLabel *labels[6];
                QLineEdit *lineEdits[6];
                QPushButton *recalculate;
                QVBoxLayout *mainLayout;
                QGridLayout *layout;
                QCustomPlot *customPlot;
                QComboBox *signalStyle;
                QWidget *body;
            
            //private slots:
            //    void GenerateNewGraph();
            
            signals:
            
            };
            
            #endif // UIGRAPH_H
            

            pidfunction.h

            #ifndef PIDFUNCTION_H
            #define PIDFUNCTION_H
            
            #include "functiongenerator.h"
            #include <QObject>
            
            enum FunctionType {_line, _sin, _saw, _triangle, _square, _curvTriCave, _curTriVex };
            
            class PIDFunction : public FunctionGenerator, public QObject
            {
                Q_OBJECT
            
            public:
                PIDFunction();
                void GenerateNextPoint();
                QVector<double> yOutput;
                void Process(double val);
                double Calculate(double setpoint, double pv);
            
                void SetP(double p);
                void SetI(double i);
                void SetD(double d);
                void SetLoopInterval(int _dt);
                void SetTargetValue(double t);
                //void SetPeriod(int p);
            
                void SetWaveform(int);
            
                void Reset();
            
            public slots:
                void GenerateNewRun();
            
            private:
                // proportional, integral, derivative
                double kp, ki, kd;
                // loop interval time
                double dt;
                // Min/Max of manipulated variable
                double max, min;
                // integral
                double integral;
                // Previous Error
                double pre_error = 0;
                // Stored Error
                double storedError = 0;
                // Target Value
                double target = 0;
                // Period
                int period = 10;
            
                double previousError;
            
                FunctionType ft;
            };
            
            #endif // PIDFUNCTION_H
            
            KroMignonK Offline
            KroMignonK Offline
            KroMignon
            wrote on last edited by KroMignon
            #5

            @JPatrick said in QT Signals And Slots Between 2 Classes:

            // UI Component
            graph = new UIGraph(this);
            QWidget* graphObject = graph->SetupUI();
            
            // PID Component
            pid = new PIDFunction();
            // Neither of these successfully resolve
            connect(&graph, SIGNAL(CreateNewRun()), this->pid, SLOT(GenerateNewRun()));
            connect(&graph, &UIGraph::CreateNewRun, &pid, &PIDFunction::GenerateNewRun);
            

            No this cannot work, connect() sender and receiver should be pointers not pointer of pointer!

            // Old syntax
            connect(graph, SIGNAL(CreateNewRun()), pid, SLOT(GenerateNewRun()));
            // new syntax
            connect(graph, &UIGraph::CreateNewRun, pid, &PIDFunction::GenerateNewRun);
            
            

            It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

            1 Reply Last reply
            2
            • JonBJ JonB

              @JPatrick said in QT Signals And Slots Between 2 Classes:

              // Neither of these successfully resolve
              connect(&graph, SIGNAL(CreateNewRun()), this->pid, SLOT(GenerateNewRun()));
              connect(&graph, &UIGraph::CreateNewRun, &pid, &PIDFunction::GenerateNewRun);
              

              Hi and welcome.

              If you showed/looked at the error message you would get further.

              Get rid of the SIGNAL/SLOT() macros approach and stick to the second case new style for all your work. There the error message should be telling you (read it carefully!) what is wrong with your parameter types. (Hint: &graph and &pid are wrong, you're almost there but over-complicating....)

              J Offline
              J Offline
              JPatrick
              wrote on last edited by JPatrick
              #6

              @JonB and @KroMignon

              Good grief I feel like a fool.

              connect(graph, &UIGraph::CreateNewRun, pid, &PIDFunction::GenerateNewRun);
              

              worked without issue, and now I'm running again. Thank you for pointing out the obvious to me.

              JonBJ 1 Reply Last reply
              1
              • J JPatrick

                @JonB and @KroMignon

                Good grief I feel like a fool.

                connect(graph, &UIGraph::CreateNewRun, pid, &PIDFunction::GenerateNewRun);
                

                worked without issue, and now I'm running again. Thank you for pointing out the obvious to me.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @JPatrick
                You were close, for a noob you did well on your own, you should see some of the questions we get! :) Like I said, do yourself a favour and stick to that new style connect() syntax, then you get compile-time incompatibility error messages, look at those closely and you should be able to discern the cause.

                1 Reply Last reply
                0

                • Login

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