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";
-
hi
code seems fine.
did you check return value ofqDebug() << "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.
-
Hi,
checkInput is called in patientinfo's constructor which means the signal is emitted before the connection happens.
-
@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 mySigthe button does not disable though
-
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.
-
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.
-
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.
-
I followed this post: https://forum.qt.io/topic/4847/how-to-enable-a-submit-button-after-multiple-form-fields-have-been-verified/13
and now it works! Thank you