Search code examples
c++qtsignals-slots

Slot not being called after signal emitted in QT Creator


Why isn't my slot sl_classASaveDataFromClassB in ClassA being called? I am emitting a signal to the slot from another class (ClassB) and expect that the function sl_classASaveDataFromClassB is called when the ClassB::closeEvent function is called.

The flow of events is as follows:

  1. On program launch, ClassA constructor is called which sets up the signal/slot connection: connect(ClassB::getInstance(), SIGNAL(&ClassB::sig_ClassBData(float,float)), this, SLOT(sl_classASaveDataFromClassB(float,float))); where I connect ClassB's signal to ClassA's SLOT function.
  2. user presented with general config screen. The code for this screen contains a struct with config variables.
  3. User clicks an button which launches a window where they enter two float values relating to float two values (blahA & blahB).
  4. User selects "Save" icon which calls ClassB::on_btnDataSave_clicked()
  5. This invokes the closeEvent QT function ClassB::closeEvent(QCloseEvent *event) which emits the signal sig_classBData

Placing breakpoints in the code shows that the overidden ClassB::closeEvent is called on window close, and the signal is emitted, however the slot function is never called.

ClassA.c

ClassA_UI::ClassA_UI(QWidget *parent, c_Instrument *Instrument) :
    QFrame(parent),
    ui(new Ui::ClassA_UI)
{
        connect(ClassB::getInstance(), SIGNAL(&ClassB::sig_ClassBData(float,float)), this, SLOT(&sl_classASaveDataFromClassB(float,float)));
}

void ClassA_UI::on_btnClick_setVals()
{
    ClassB::getInstance()->show();
}

void ClassA_UI sl_classASaveDataFromClassB(float latitude, float longitude)
{
    qDebug() << "test";
}

ClassA.h

class ClassA_UI : public QFrame
{
    Q_OBJECT

public:
    explicit ClassA_UI(QWidget *parent = 0);
    ~ClassA_UI();
public slots:
     sl_classASaveDataFromClassB(float blahA, float blahB)
}



ClassB* ClassB::getInstance()
{
    if(instance == nullptr){
        instance = new ClassB();
    }
    return instance;
}

ClassB.c

ClassB* ClassB::instance = nullptr;

ClassB::ClassB(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ClassB)
{
    ui->setupUi(this);

    data = new data;

    connect(this, SIGNAL(sig_ClassBUpdateBox(QString, QString)), this, SLOT(sl_GeoLocationUpdateBox(QString,QString)),Qt::QueuedConnection);
}

void ClassB::on_btnDataSave_clicked()
{
    // save long lat values here

    location->blahA = ui->lineEdit_blahA->text().toFloat();
    location->blahB = ui->lineEdit_blahB->text().toFloat();

    // Values set successfully
    emit sig_ClassBUpdateBox( "Location Updated", "Location update applied.");
    this->close();

}

void ClassB::closeEvent(QCloseEvent *event)
{
    qDebug() << "closeEvent" ;
    emit sig_classBData(data->blahA, data->blahB);

    event->accept();
}

ClassB.h

namespace Ui {
class ClassB;
}

class ClassB : public QWidget
{
    Q_OBJECT

public:
    explicit ClassB(QWidget *parent = nullptr);
    ~ClassB();

private:
    Ui::ClassB *ui;
private:
    typedef struct  {
        float blahA;
        float blahB;
    } data;

    data *location;

    static ClassB* instance;
public:
    static ClassB* getInstance();
signals:
    void sig_ClassBUpdateBox(QString Title, QString Message);
    void sig_classBData(float blahA, float blahB);

};


Solution

  • I have solved this by modifying the connection string to the following:

    connect(ClassA::getInstance(), SIGNAL(sig_ClassBData(float,float)), this, SLOT(sl_classASaveDataFromClassB(float,float)), Qt::QueuedConnection);
    

    I'll share my findings for anyone that also runs into a similar issue.

    So the connect function actually returns a boolean true/false for the connection. In my constructor I added a temp boolean variable that I placed a breakpoint at, and that showed me the connection was returning false which indicated to me that the reason why the slot in classA was not being called was because the connection was never successfully set up.

    From the documentation, the connect string is as follows:

    QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
    

    Breaking that down:

    // Send class
    const QObject *sender = w_sfmGeoLocConfiguration::getInstance(), 
    const char *signal = SIGNAL(sig_GeoLocationData(float,float)), 
    
    // Recieve class
    const QObject *receiver = this,
    const char *method = SLOT(sl_updateGeoLocation(float,float)), 
    Qt::ConnectionType type = Qt::QueuedConnection