Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Access from Child in another CPP Class



  • Hi, I have a MainWindow.cpp file which initialised my UI.
    However, I wnat to create a new class (lets say conlinecam.h and conlinecam.cpp) and start the timer from the new class. How can I do so?

    I tried to make it as a QObject and Pass in the UI from the MainWindow so that I can update the text edit. the codes are as follows.

    conlinecam.h

    #ifndef CONLINECAM_H
    #define CONLINECAM_H
    
    #include <mainwindow.h>
    #include <QMainWindow>
    
    class conlinecam : public QObject
    {
        Q_OBJECT
    public:
        conlinecam(Ui::MainWindow& ui);
        ~conlinecam();
        QTimer* camtimer;
    
    public slots:
        void update_screen(Ui::MainWindow& ui);
    };
    
    #endif // CONLINECAM_H
    

    conlinecam.cpp

    #include "conlinecam.h"
    #include "ui_mainwindow.h"
    #include "mainwindow.h"
    
    conlinecam::conlinecam(Ui::MainWindow& ui) : QObject()
    {
         camtimer = new QTimer(this);
         ui.textEdit->append("Online was Clicked");
         connect(camtimer,SIGNAL(timeout()), this, SLOT(update_screen(Ui::MainWindow& ui)));
         camtimer->start(30);
    
    }
    
    void conlinecam::update_screen(Ui::MainWindow& ui){
        ui.textEdit->append("online is working.");
    }
    
    conlinecam::~conlinecam()
    {
        camtimer->stop();
    }
    
    

    However, when i run the program, I faced this issue "QObject::connect: No such slot conlinecam::update_screen(Ui::MainWindow& ui) in ..\QtBladder\conlinecam.cpp:8"

    I tried QMake and Rebuild on the project but it is not showing. Any Idea how to solve this issue?

    EDIT:: The reason why I am passing the Ui::MainWindow* ui in update_screen() is that I want to use the ui's widgets such as TextEdit, Labels etc. If there is an example, please enlighten me


  • Qt Champions 2019

    @Stevendragoes said in Access from Child in another CPP Class:

    connect(conlinecam.camtimer,SIGNAL(timeout()), this, SLOT(update_screen()));

    Not like that, because now you're exposing the internals of your child class to the outside world.
    Do it like this:

    connect(conlinecam,SIGNAL(update()), this, SLOT(update_screen()));
    

    Here your child class provides update() signal which is emitted when the timeout signal of your timer (which should now be private!) is emitted. This way your parent class does not need to know that the child class uses a timer (and access that timer directly), it only needs to know that the child emits update() signal if there is a need to update. This concept is called encapsulation in object oriented programming.
    Just a tip: in Qt you can connect signals to signal. So you can connect the timeout signal from the timer to update signal in your child class.


  • Qt Champions 2019

    @Stevendragoes said in Access from Child in another CPP Class:

    Pass in the UI

    Please don't do such hacks!
    The correct was is that the child does not know anything about parent. The child should simply emit a signal which is then connected to a slot in the parent. Parent then knows how to use its own UI and what to do with the signal.



  • Hi @jsulm so, what you are saying is that I can only initialise the QTimer to start thats all? and the connect statement should be.

    connect(conlinecam.camtimer,SIGNAL(timeout()), this, SLOT(update_screen()));
    

    where update_screen should be implemented inside the mainwindow.cpp?

    EDIT: The syntax for the sender might be wrong because I didn't write it in my program yet. So, how can i make my code to be more spread out across multiple cpp files? because I don't want to lump all together in mainwindow.cpp with 1000+ lines of codes? how can I modify and clean my code?


  • Qt Champions 2019

    @Stevendragoes said in Access from Child in another CPP Class:

    connect(conlinecam.camtimer,SIGNAL(timeout()), this, SLOT(update_screen()));

    Not like that, because now you're exposing the internals of your child class to the outside world.
    Do it like this:

    connect(conlinecam,SIGNAL(update()), this, SLOT(update_screen()));
    

    Here your child class provides update() signal which is emitted when the timeout signal of your timer (which should now be private!) is emitted. This way your parent class does not need to know that the child class uses a timer (and access that timer directly), it only needs to know that the child emits update() signal if there is a need to update. This concept is called encapsulation in object oriented programming.
    Just a tip: in Qt you can connect signals to signal. So you can connect the timeout signal from the timer to update signal in your child class.



  • @jsulm Noted on the Encapsulation portion. I will try it out now.

    But What about the cleaning up the code? Lets say I want to draw automated Arrows on the UI Label, I should create a new class to draw on the label?

    Edit: I just want the code to be modular and each cpp classes are meant to do something in my program. Hope you don't mind explaining how it can be achieved


  • Qt Champions 2019

    @Stevendragoes said in Access from Child in another CPP Class:

    Edit: I just want the code to be modular and each cpp classes are meant to do something in my program

    This is good, but you should avoid tightly coupled classes. Means: do not expose private implementation details to the outside world, only well defined interfaces.

    Regarding painting/drawing on a widget: for that you need to subclass (so create a new class :-)) and override https://doc.qt.io/qt-5/qwidget.html#paintEvent Here you can see how to paint: https://doc.qt.io/qt-5/qpainter.html



  • @jsulm Hello, I have implemented it but it still says no such signal.

    What i have done is this.
    When I press a button, the new class will be initiated and I connected the cam update to the slot of update_screen();
    The codes are as follows:
    In my mainwindow.cpp I have the following SLOT for button press:

    void MainWindow::on_online_clicked()
    {
        conlinecam* cam = new conlinecam();
        connect(cam, SIGNAL(update()), this, SLOT(update_screen()));
    }
    

    conlinecam.h

    #ifndef CONLINECAM_H
    #define CONLINECAM_H
    
    #include <mainwindow.h>
    #include <QMainWindow>
    
    class conlinecam : public QObject
    {
        Q_OBJECT
    public:
        conlinecam();
        ~conlinecam();
    private:
        QTimer* camtimer;
    };
    
    #endif // CONLINECAM_H
    

    conlinecam.cpp

    #include "conlinecam.h"
    #include "ui_mainwindow.h"
    #include "mainwindow.h"
    
    conlinecam::conlinecam() : QObject()
    {
         camtimer = new QTimer(this);
         camtimer->start(30);
    }
    
    
    conlinecam::~conlinecam()
    {
        camtimer->stop();
    }
    
    

    am I doing something wrong here?


  • Qt Champions 2019

    @Stevendragoes said in Access from Child in another CPP Class:

    but it still says no such signal.

    Because you don't have such signal in conlinecam - you need to add it by yourself.



  • @jsulm
    Alright I fixed it by writing two lines in conlinecam.h code

    signals:
        void update();
    

    then connect using this code

    
    conlinecam::conlinecam() : QObject()
    {
         camtimer = new QTimer(this);
         connect(camtimer,SIGNAL(timeout()),this,SIGNAL(update()));
         camtimer->start(30);
    }
    
    

    it is working but it is the correct way?


  • Qt Champions 2019

    @Stevendragoes Looks good


Log in to reply