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

Calling a Function when a Signal is Emitted from Another Class



  • Hello,
    I have two ui in different classes.
    In classA ui file has; comboBox and StackedWicked with there pages, and
    In classB ui file has; pushButton and textEdit.
    When I release pushButton in classB, I would like to add the text in textEdit into comboBox which is stated classA.
    And I would like to also change the currentIndex of the stackedWidget in classA.

    So, there are two changes I would like to do in first class when I release the button. Therefore, I connected a signal my pushButton.released() and a slot which emits.

    ClassB.cpp

    Second::Second(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Second)
    {
        ui->setupUi(this);
        connect(ui->pushButton, SIGNAL(released()), this, SLOT(emitthesignal()));
    }
    
    void Second::emitthesignal() {
         emit;
    }
    

    I have tried related solutions found on the previous topics but I could not make it work.

    Any suggestion appriciated. Thank you!



  • @qtross said in Calling a Function when a Signal is Emitted from Another Class:

    void Second::emitthesignal() {
        emit; // it looks you're not emitting anything...
    }
    

    Take a look at Signals & Slots introduction to check how to define the signal and its arguments (in your case, you'll be emitting the value of the textEdit from class B)



  • @Pablo-J-Rogina thank you for your reply.
    It is little bit confusing topic, but I have achieved this. However, i did not get any error but it didt work.

    in second.h

    #include "MainWindow.h"
    #include "ui_MainWindow.h"
    
    public:
    MainWindow *main;
    
    signals:
    textForCombo(QString try);
    

    in second.cpp

    void Second::emitsignal(const QString &arg1)
    
    {   
        arg1=ui->textEdit->toPlainText();
        emit textForCombo(arg1); 
        connect(this, SIGNAL(textForCombo(QString)),main, SIGNAL(TextReceive(QString))); 
    }
    

    MainWindow.h:

    signals:
    TextReceive(QString try2);
    private slots:
    void forstdchange(const QString str);
    

    And in MainWindow.cpp:

    {
        ui->setupUi(this);
        connect(this , SIGNAL(TextReceive(QString)),this, SLOT(forstdchange(QString)));
    }
    
    void MainWindow::forstdchange(const QString str) {
    std::string forstd=str.toStdString();
    ui->comboBox->addItem(forstd.c_str());
    
    }
    

  • Lifetime Qt Champion

    @qtross

    I'll just add some comments to help you understand your own code:

    void Second::emitsignal(const QString &arg1)
    {   
        arg1=ui->textEdit->toPlainText(); // How can that work? arg1 is const
        emit textForCombo(arg1); 
        connect(this, SIGNAL(textForCombo(QString)),main, SIGNAL(TextReceive(QString)));  // what is that for?
        // Note that you add an connection everytime the emitsignal function is run, which is NOT what you want
       // Also, you already emit in the line above, so you *don't* need this connect here
    }
    
    void MainWindow::forstdchange(const QString str)  // Change to 'const QString &str'
    {
      std::string forstd=str.toStdString(); // That looks overly complicated
      ui->comboBox->addItem(forstd.c_str()); // and creates subtile errors with non-ASCII chars
    
      ui->comboBox->addItem(str); // That is much easier
    }
    

    Regards



  • @aha_1980 Thank you for your reply.

    connect(this, SIGNAL(textForCombo(QString)),main, SIGNAL(TextReceive(QString)));
    

    Why I have added this line is I though I need to declare again for accessing first class.ui
    with the SIGNAL(TextReceieve(QString)). Therefore, I created void textForCombo.

    I did not know I can add directly QString as item into comboBox. I thought I needed to convert it to first std::string then to char.

    Now, I did changes you suggested and added this line to mainwindow.cpp,

       connect(this, SIGNAL(emitsignal(QString)), this, SLOT(forstdchange(QString)));
    

    though I added emitsignal in slots-header but I have this error;

    Object::connect: No such slot Second::emitthesignal(QString) in ..\untitled\second.cpp:10
    

    Sorry for taking long. I am new to qt and it takes time to understand thank you again.


  • Lifetime Qt Champion

    @qtross said in Calling a Function when a Signal is Emitted from Another Class:

    connect(this, SIGNAL(textForCombo(QString)),main, SIGNAL(TextReceive(QString)));

    To use Signals & Slots effectively, the pattern should always be:

    connect(member, SIGNAL(x), this, SLOT(y)); to achive loose coupling. Other way round your objects are harder to re-use.

    Object::connect: No such slot Second::emitthesignal(QString) in ..\untitled\second.cpp:10

    This error message has nothing to do with this connect, IMHO:

    connect(this, SIGNAL(emitsignal(QString)), this, SLOT(forstdchange(QString)));

    Also, you should check out the new connect syntax:

    https://doc.qt.io/qt-5/signalsandslots.html
    https://wiki.qt.io/New_Signal_Slot_Syntax

    Regards



  • Hi again, I updated my code, it seems logical now but I still could not make it work.
    I must be missing something simple or doing still something silly.

    I also uploaded:
    https://ufile.io/dambwl0c
    Ui screens:
    https://ibb.co/xC6gqTz

    and There is my code;

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        void on_pushButton_clicked();
        void addtoCombo(QString text);
    private:
        Ui::MainWindow *ui;
    };
    
    #endif // MAINWINDOW_H
    

    mainwindow.cpp:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "secondclass.h"
    #include <QDebug>
    #include <iostream>
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        SecondClass* second = new SecondClass;
        connect(second, SIGNAL(update(const QString)), this, SLOT(addtoCombo(const QString)));
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        SecondClass* window = new SecondClass;
        window->show();
    
    }
    
    void MainWindow::addtoCombo(QString text) {
    
        qDebug() <<"I have been called" << endl;
        ui->comboBox->addItem(text);
        ui->stackedWidget->setCurrentIndex(1);
    
    }
    

    secondclass.h:

    #ifndef SECONDCLASS_H
    #define SECONDCLASS_H
    
    #include <QWidget>
    
    namespace Ui {
    class SecondClass;
    }
    
    class SecondClass : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit SecondClass(QWidget *parent = nullptr);
        ~SecondClass();
    
    private:
        Ui::SecondClass *ui;
    signals:
         void update(const QString text);
    private slots:
         void on_pushButton_clicked();
    };
    
    #endif // SECONDCLASS_H
    

    seconclass.cpp

    #include "secondclass.h"
    #include "ui_secondclass.h"
    
    SecondClass::SecondClass(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::SecondClass)
    {
        ui->setupUi(this);
    }
    
    SecondClass::~SecondClass()
    {
        delete ui;
    }
    
    void SecondClass::on_pushButton_clicked()
    {
         emit update("it adds");
    }
    

  • Moderators

    @qtross said in Calling a Function when a Signal is Emitted from Another Class:

    jup, the problem is you do not connect the signal to the instance that is shown.

    in your constructor you create a SecondClass instance

    {
    ui->setupUi(this);
    SecondClass* second = new SecondClass;
    connect(second, SIGNAL(update(const QString)), this, SLOT(addtoCombo(const QString)));

    }

    and on pushbutton clicked, you create yet an other instance of your SecondClass and show that one.
    But this one has no connects to it!

    void MainWindow::on_pushButton_clicked()
    {
    SecondClass* window = new SecondClass;
    window->show();

    }

    make SecondClass* second a member of your main window.h

    //Constructor than changes to
    ui->setupUi(this);
    second = new SecondClass;
    connect(second, SIGNAL(update(const QString)), this, SLOT(addtoCombo(const QString)));
    
     void MainWindow::on_pushButton_clicked()
     {
        second->show();
    }
    


  • @J.Hilk , it worked finally, Thank you so much!


Log in to reply