Solved same signal-slot connection in two windows
-
@russjohn834 You should avoid global variables as much as possible.
Just pass the pointer to api to Settings & Patients constructors... -
Did you ensure that the connection in
Patients
is done before the signaltetra_grip_api::tetraGripEvent
is emitted? SomeqDebug
s around connection, in the very first line ofPatients::eventHandlerTwo
and in the deconstructor ofPatients
should help to prove that. -
@russjohn834 said in same signal-slot connection in two windows:
@JonB
Correct. I actually did not do anything other that making apiinstance as global in main.cpp. That might be the issue. But dont know how to proceed. How do I make Patients classes know about global api instance?I truly, truly do not understand. You said your program runs but does/does not behave properly in the cases you mentioned. I asked how you can even compile your
Settings
/Patients
modules/.cpp
source files which contain the lineconnect(&api, ...
, whenapi
is defined inmain.cpp
? From what you have said/shown they should error at compile-time with a "No such variable:api
" message. So I will leave others to help, who obviously understand your source code better than I. -
@JonB Yes, that's interesting. You can't include
main.cpp
inSettings
or inPatients
. Somain.cpp
s linetetra_grip_api api; //-------------> api instance
isn't visible anywhere!
-
@russjohn834 If you are using QtCreator: When you go on the
&api
in your connect statements in bothSettings
andPatients
and press F2 - where does it lead you to? -
From both
Settings
andPatients
,&api
leads me here:#ifndef TETRA_GRIP_API_H #define TETRA_GRIP_API_H #include <QObject> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <QLabel> #include <QMessageBox> #include <QTimer> #define _CRT_SECURE_NO_DEPRECATE class tetra_grip_api : public QObject { Q_OBJECT public: explicit tetra_grip_api(QObject *parent = nullptr); #define MAX_CONFIG_FILE_LENGTH (10000) void static send_config_file(QByteArray config, bool nonvolatile); void static send_long_register(uint8_t, uint32_t, uint8_t *); void static stimulation_set_current(unsigned int, unsigned int); QSerialPort *serial = nullptr; QTimer autoConnectionTimer; bool tryToAutoconnect; signals: void tetraGripEvent(STIM_GUI_TOPIC_T topic, uint8_t reg, uint32_t value); public slots: void openSerialPort(); void closeSerialPort(); void readData(); private slots: void ErrorHandler(QSerialPort::SerialPortError error); private: QString comPortName; }; extern tetra_grip_api api; //----------> it leads me here #endif // TETRA_GRIP_API_H
-
@russjohn834 said in same signal-slot connection in two windows:
extern tetra_grip_api api;
You really should not do it like this. Pass pointer to the constructors of the classes which need it.
-
@jazzco2 said in same signal-slot connection in two windows:
@JonB Yes, that's interesting. You can't include main.cpp in Settings or in Patients.
No, but you might be including
main.h
, and maybe you haveextern tetra_grip_api api;
there, that's the sort of thing I was trying to understand. Which finally you have shown is actually intetra_grip_api.h
, which I guess you are including into each of them?For the line there
extern tetra_grip_api api;
does the docs for tetra_grip_api say you are responsible for defining
tetra_grip_api api;
yourself like you have done inmain.cpp
, or does it say they (the library) are defining that global instance and you are supposed to use their instance? -
@russjohn834 Yes, pass the pointer - and then your api can be a local variable in main. No need to define it outside as main lives as long as the application is running.
-
Could you give me an example to show how do I pass a pointer to the constructor of the classes? for ex. if I need to use it in in
Settings
andPatients
classes ? -
@russjohn834 said in same signal-slot connection in two windows:
Could you give me an example to show how do I pass a pointer to the constructor of the classes?
Well
tetra_grip_api api; Settings settings(&api);
Of cource you have to change the constructor, but this is C++ basic stuff.
-
it did not mention anything like that. My primary requirement is to use
tetra_grip_api
(which is a class containing all serial communication objects) instance in every form class. That's why I made it global, but now I realize it's not a good way of programming! -
@russjohn834 said in same signal-slot connection in two windows:
Yes and no, it gets complicated. You may not need to pass it around that way.It looks like the
tetra_grip_api
is something in-house to you, it does not exist on the web. You have shown thattetra_grip_api.h
file contains the line:extern tetra_grip_api api; //----------> it leads me here
You should ask the author of that file whether he intends:
-
It is up to you to go
tetra_grip_api api
once in one of your own files, in order to define it, as you have done in yourmain.cpp
; OR -
The tetra_grip_api library already contains this definition for you, and you are supposed to use that one.
For now, humour me:
Go into your
main.cpp
. Locate the line which reads:tetra_grip_api api; //-------------> api instance
Now comment out that line.
Try to rebuild & relink. What happens? Do you end up, after the linking, with an error message like: "Unresolved symbol: ''tetra_grip_api", or not?
-
If there is no error, see whether your program behaves correctly now.
-
If there is an error, unfortunately it's time we saw all your relevant code which should work but does not, because there is way too much incomplete information in what you have posted. I hesitate to say this, because I have a bad feeling that's going to be (at least) 3 .
cpp
files & 3.h
. files. Which is an awful lot for to paste and for us to look through :( If you could cut it down to a relevant, minimal subset which reproduces the bad behaviour you say you see, that would be really good....
-
-
@JonB Thanks a lot for your feedback.
Commenting out of
tetra_grip_api api
in themain.cpp
did end up in multiple errors with "Unresolved external symbol class tetra_grip_api api".From the suggestions from you guys, I feel like there is something wrong in making use of global variables. I should try also the other way of passing pointer to the class.
But I was trying to understand a reason program behaves this way.
As I mentioned earlier , If I call
Patients
behaves badly if I call it fromSettings
. But instead If I call bothPatieints
andSettings
in themain
(as shown below), both behave as expected. Do you immedatly think of any reason for this!?#include <QApplication> tetra_grip_api api; int main(int argc, char *argv[]) { QApplication a(argc, argv); api.openSerialPort(); QObject::connect(api.serial, SIGNAL(readyRead()), &api, SLOT(readData())); QObject::connect(api.serial, SIGNAL(error(QSerialPort::SerialPortError)),&api, SLOT(ErrorHandler(QSerialPort::SerialPortError))); // error handling Settings w(nullptr); //---->this behaves right Patients v(nullptr); //---- >this behaves right v.show(); w.show(); return a.exec(); }
-
@russjohn834
No, because you show the case which works OK. We need to see exactly howSettings
callsPatients
, plus the signal connections, with whatever is relevant to that case, to judge where the problem is. -
This is how I call
Patients
fromSettings
void Settings::on_pushButton_patients_clicked() { this->close(); stagetwo = new Patients(this); stagetwo -> show(); }
where
stagetwo
is publicpublic: Settings(QString,QWidget *parent = nullptr); ~Settings(); Patients *stagetwo;
In the
Patients
signal connection is as below:Patients::Patients( QWidget *parent) : QMainWindow(parent), ui(new Ui::Patients) { ui->setupUi(this); connect(&api, &tetra_grip_api::tetraGripEvent,this, &StageTwoPatients::eventHandlerTwo); }
-
@russjohn834 said in same signal-slot connection in two windows:
void Settings::on_pushButton_patients_clicked()
{
this->close();
stagetwo = new Patients(this);
stagetwo -> show();
}Just to humour me, replace by
void Settings::on_pushButton_patients_clicked() { // this->close(); // stagetwo = new Patients(this); stagetwo = new Patients(nullptr); stagetwo -> show(); }
Any better behaviour?
-
Can't see any change.
-
@russjohn834
Very last thing: how do you know slot is not being called? Please place a breakpoint on it. -
@JonB
I did try with a breakpoint, and convinced that the slot is not being called when thePatients
window is constructed.
So I guess that's a serious issue using global class instance. Though I was trying to understand why this is happening ..