Solved same signal-slot connection in two windows
-
Hi all,
I just noticed this thing if I call both my
Settings
andPatients
from my main the connection is successful (see below)#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); w.show(); Patients v(nullptr); //---------> this makes connection successfull v.show(); return a.exec(); }
but instead, if I call
Patients
fromSettings
even though the connection is successful im not getting the expected output.My signal source
api
is a global variable which is initialized in the main as shown above.
So constructing both classes in the main makes connection ok and I'm gettting expected output. But if I call one window from other makes connection true but my slot is not being called at all.What is the reason for this?
-
@russjohn834
If you're asking me to guess, show how you gain access totetra_grip_api api;
fromSettings
/Patients
? In these cases where do you do theconnect()
s from? And, how do you know yourconnect()
s are successful? -
Hi,
@russjohn834 said in same signal-slot connection in two windows:
QObject::connect(api.serial, SIGNAL(readyRead()), &api, SLOT(readData()));
QObject::connect(api.serial, SIGNAL(error(QSerialPort::SerialPortError)),&api, SLOT(ErrorHandler(QSerialPort::SerialPortError))); // error handlingSince serial is internal to
api
why don't you connect it in the constructor of your tetra_grip_api class ? -
This is how I make the connection in
Settings
.Settings::Settings(QString patientLabel, QWidget *parent) : QMainWindow(parent) , ui(new Ui::Settings) { ui->setupUi(this); connect(&api, &tetra_grip_api::tetraGripEvent,this, &Settings::eventHandler); }
Connection is successfull (
qDebug()<<connect(....)
gives TRUE) also the aQLabel
and an LED in theeventHandler
slot works perfectly.In the same way I try to connect in the
Patients
:Patients::Patients(QWidget *parent) : QMainWindow(parent) , ui(new Ui::Patients) { ui->setupUi(this); connect(&api, &tetra_grip_api::tetraGripEvent,this, &Patients::eventHandlerTwo); }
here connection is successfull (
qDebug()<<connect(....)
gives TRUE) but the aQLabel
and an LED in theeventHandlerTwo
are not working. -
@russjohn834
How do I know&api
refers to the same, global, initializedapi
instance in both cases?
And I see nothing in code about anyQLabel
in either case, not mentioned by you before...
You have to supply the necessary/relevant code if you want people to help.
Use a debugger to make sure whether slots are being hit. -
I thought
api
should be known and accessible to all classes if intialized as global in themain.cpp
#include <QApplication> tetra_grip_api api; //-------------> api instance 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); w.show(); return a.exec(); }
Correct me if I'm wrong.
-
@russjohn834
YourSettings
&Patients
classes are defined in a different source module frommain.cpp
, right? So how do they gain access to reference theapi
symbol in order to compile?connect(&api, &tetra_grip_api::tetraGripEvent,this, &Patients::eventHandlerTwo);
I am having to tease out each bit of relevant information, one at a time....
-
@JonB
Correct. I actually did not do anything other that makingapi
instance as global inmain.cpp
. That might be the issue. But dont know how to proceed. How do I makePatients
classes know about globalapi
instance? -
@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!