Issues connecting signal and slots[SOLVED]



  • I have a pretty solid idea how signal and slots work

    I have several classes but three classes are giving me issues: mainwindow, patientinfo, and idnamebar. On mainwindow, I have a stackwidget which I added patientinfo. I created a signal on patientinfo that will detect if the patient's first name QLineEdit is empty or not. If is empty, it will tell idnamebar to disable its button. When I run the code, the button never disables.

    patientinfo.cpp

    #include "patientinfo.h"
    #include "ui_patientinfo.h"
    #include <QDebug>
    
    patientinfo::patientinfo(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::patientinfo)
    {
        ui->setupUi(this);
        //GUI
        QWidget *patientInfo = new QWidget;
        ui->allPatientInfoLayout->setAlignment(Qt::AlignCenter);
        ui->patientInfoLayout = new QVBoxLayout(patientInfo);
    
        checkInput();
    }
    
    void patientinfo::checkInput()
    {
        if (ui->firstnameLineEdit->text().isEmpty())
        {
            emit checkInputSignal();
        }
    }
    
    patientinfo::~patientinfo()
    {
        delete ui;
    }
    

    patientinfo.h

    #ifndef PATIENTINFO_H
    #define PATIENTINFO_H
    
    #include <QDialog>
    
    namespace Ui {
    class patientinfo;
    }
    
    class patientinfo : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit patientinfo(QWidget *parent = 0);
        ~patientinfo();
        void checkInput();
    
    signals:
        void checkInputSignal();
    
    private:
        Ui::patientinfo *ui;
    };
    
    #endif // PATIENTINFO_H
    

    idnamebar.cpp

    #include "idnamebar.h"
    #include "ui_idnamebar.h"
    #include <QDebug>
    
    IdNameBar::IdNameBar(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::IdNameBar)
    {
        ui->setupUi(this);
    }
    
    void IdNameBar::onCheckInput()
    {
           ui->nextButton->setEnabled(false);
    }
    
    IdNameBar::~IdNameBar()
    {
        delete ui;
    }
    

    idnamebar.h

    #ifndef IDNAMEBAR_H
    #define IDNAMEBAR_H
    
    #include <QWidget>
    
    namespace Ui {
    class IdNameBar;
    }
    
    class IdNameBar : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit IdNameBar(QWidget *parent = 0);
        ~IdNameBar();
    
    public slots:
        void onCheckInput();
    
    private:
        Ui::IdNameBar *ui;
    };
    
    #endif // IDNAMEBAR_H
    
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QDialog>
    #include <QStackedWidget>
    #include "patientinfo.h"
    #include "idnamebar.h"
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private:
        QStackedWidget *_stackedWidget;
        Ui::MainWindow *ui;
    
    protected:
        patientinfo *_patientinfo;
        IdNameBar *_idnamebar;
    };
    
    #endif // DIALOG_H
    
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QStackedWidget>
    
    MainWindow::MainWindow(QWidget *parent) : QDialog(parent),ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        _patientinfo = new patientinfo(this);
        _idnamebar = new IdNameBar(this);
    
        _stackedWidget = new QStackedWidget;
        _stackedWidget->addWidget(_patientinfo);
    //more pages here but unrelated to the question
    
        QVBoxLayout *vLayout = new QVBoxLayout;
        vLayout->addWidget(_stackedWidget);
        vLayout->addWidget(_idnamebar);
        setLayout(vLayout);
    
        connect(_patientinfo,SIGNAL(checkInputSignal()),_idnamebar,SLOT(onCheckInput()));
    }
    
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    

    I checked If I am emitting on the patientinfo.cpp with the signal with :

    qDebug()<<"checking mySig";
    emit checkInputSignal();
    qDebug()<<" mySig emitted";
    

  • Qt Champions 2016

    hi
    code seems fine.
    did you check return value of

    qDebug() << "patcon" <<   connect(_patientinfo,SIGNAL(checkInputSignal()),_idnamebar,SLOT(onCheckInput()));
    

    And I assume you put a debug() too in
    dNameBar::onCheckInput()
    and it never gets in there?



  • @mrjj It said "patcon true" and when I put debug on the idNameBar nothing outputs.


  • Lifetime Qt Champion

    Hi,

    checkInput is called in patientinfo's constructor which means the signal is emitted before the connection happens.


  • Qt Champions 2016

    @SGaist
    Ah, good spotted.



  • @SGaist I can't think of another way to write the code. Can you give me suggestions?



  • Ok so I created the connection in patientinfo.cpp and commented out the one in mainwindow.cpp

    _idNameBar = new IdNameBar;
    .
    .
    .
    connect(this,SIGNAL(checkInputSignal()),_idNameBar,SLOT(onCheckInput()));
    checkInput();
    }
    

    and on patientinfo.h I added

    #include "idnamebar.h"
    IdNameBar *_idNameBar;
    

    I get the qdebug output as :
    checking mySig
    checking slot
    emitting slot
    emitted mySig

    the button does not disable though


  • Lifetime Qt Champion

    Now it's another subtlety: the event loop has not yet started, so it's not yet propagating.

    Anyway, the current architecture doesn't look quite right. onCheckInput just disables the next button, how do you plan to enable it again ?

    What you describes sounds a bit like QWizard, you should take a look at that class.



  • @SGaist I really do not want to use QWizard since I don't want that exact look. I know I have to enable it again but I am doing it step by step. I just want to make the button disabled if that field is empty. Once I can make that work, I will work on enabling it again once there is something in that field which is the patient name.


  • Lifetime Qt Champion

    Then you should rather add a signal to your patientinfo class that contains a boolean parameter to tell whether the its content is empty or not and connect that signal to your IdNameBar class. patientinfo should not have to care nor know about IdNameBar, it's not its responsibility.



  • @SGaist I have tried doing that but nothing happens still. The qdebug tells me i did go to the slot but the button is still enabled no matter what.


  • Lifetime Qt Champion

    Since you don't want to disable the button at construction time (which would be logical since no validation has been done), then you must trigger the check after the event loop has started. You can use a single shot QTimer with a timeout at 0 for that.



  • Ohh so you mean to disable the button at the beginning no matter what? I guess that makes sense. Ill try that!



  • I just want to remind you that many errors can be caught if you use the new Qt Connect syntax.




Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.