PDA

View Full Version : use signal&slot between two tabs



stella1016
25th July 2008, 14:23
I have a QTabWidget, and two classes, display1 and display2, are two tab members. I want to transfer some data, say a bool flag, between these two tabs:



tabWidget = new QTabWidget;
display1 = new Display1 ();
display2= new Display2()
tabWidget->addTab(display1 , tr("Online"));
tabWidget->addTab(display2, tr("Offline"));

connect(Display1, SIGNAL(sendout(bool)), Display2, SLOT(receive(bool)));


In class Display1.h:


signals:
void sendout(bool flag);

In class Display1.cpp, one of its methods does this:


bool flag = true;
emit sendout(flag);


In class Display2.h:


public slots:
void receive(bool flag);


In class Display2.cpp:


void Display2::receive(bool flag)
{
printf("I got one message. \n");
}


I got LINK ERROR:
Error 6 error LNK2001: unresolved external symbol "protected: void __thiscall Display1::sendout(bool)" (?sendout@Display1@@IAEX_N@Z) Display1.obj

I have no idea where is the problem....Can anyone help me? Thanks

wysota
25th July 2008, 15:45
You didn't moc the header file. Are you using qmake?

stella1016
25th July 2008, 16:45
You didn't moc the header file. Are you using qmake?


I have the moc already. This is strange. When I delete the SIGNAL in Display1, everything is running. The problem seems in Display1. But I can't findany error there...

wysota
25th July 2008, 16:53
What do you mean you have the moc? Are you compiling and linking the file that moc generates for your class? Did you remember about the Q_OBJECT macro?

stella1016
25th July 2008, 17:33
What do you mean you have the moc? Are you compiling and linking the file that moc generates for your class? Did you remember about the Q_OBJECT macro?

Oh, I find out that in the .h files I don't have the configurations any more. Strange, I've set them in the past.... Maybe erased during copy and paste.

Thanks very much!!!!!!! I think my problem is solved!!!!

stella1016
25th July 2008, 17:36
I know why... because I changed to release model from debug model
(I am using visual studio)....

stella1016
25th July 2008, 17:52
Hi, I have a another question.
If I want to emit something not simple as bool but my own class instance, this also can be done via SIGNAL & SLOTS?

muellerp
25th July 2008, 17:57
Hi, I have a another question.
If I want to emit something not simple as bool but my own class instance, this also can be done via SIGNAL & SLOTS?

Yes, but just read about Signal and Slots in Docu in case you want e.g. Queued Connection.

stella1016
25th July 2008, 18:15
I doubt that whether SIGNAL & SLOT can be synchronized...
In my old project, I need to update a QGLWidget with the new camera output data. I used SIGNAL & SLOT. But sometimes the two SIGNALS emitted, but only one SLOT responds.
If anyone interested, I can post the code.

wysota
25th July 2008, 18:19
I doubt that whether SIGNAL & SLOT can be synchronized...
Signals & slots can be synchronized.


In my old project, I need to update a QGLWidget with the new camera output data. I used SIGNAL & SLOT. But sometimes the two SIGNALS emitted, but only one SLOT responds.

This is hardly possible. You must have done something wrong.

stella1016
25th July 2008, 18:50
I hope I did something wrong. Maybe you can help me solve my old problem. I post my code here. My app is to display the camera output images in QGLWidget.

MyThread: in its run method, it does the while-loop


run()
{
while(flag)
{
IplImage *lp_color = t_camera.get_image();
myQLWidget->setCurrentImageIpl(lp_color);
cvReleaseImage(&lp_color);
}
}


MyQLWidget: in charge of updating the texture when it receives any image.
I am using SIGNAL & SLOT in MyQLWidget, because in method setCurrentImageIpl(), I cannot directly call updateGL(). This is because OpenGl & Thread issue... So in setCurrentImageIpl() I emit a SIGNAL to a SLOT, the SLOT will do updateGL() for me.


MyQLWidget::setCurrentImageIpl()
{

...(set image)
imageData = ...;
update = true;
emit newData();

}


newData is connect to SLOT updateImage()



MyQLWidget::updateImage()
{
this->updateGL();
}

MyQLWidget::paintGL()
{
if(update)
glTexSubImage2D = (.....imageData);
}


During displaying the first few frames that grasped by camera, my program crashes. Not every time. I don't know where is the problem. When it crashes, the reason is that the imageData is not set jet, so when update texture it crashes.

I set breakpoint, and found that in the first few steps, ...emit... executes twice, but updateImage() only once. Maybe this causes the crash, I am not sure.

Hard to explain what I did in my code here. :(

stella1016
25th July 2008, 18:50
why I posted twice..

wysota
25th July 2008, 19:17
I hope I did something wrong. Maybe you can help me solve my old problem. I post my code here. My app is to display the camera output images in QGLWidget.

MyThread: in its run method, it does the while-loop


run()
{
while(flag)
{
IplImage *lp_color = t_camera.get_image();
myQLWidget->setCurrentImageIpl(lp_color);
cvReleaseImage(&lp_color);
}
}

This is bad. You can't access widgets from other threads and I can't stress that more. You should have emitted a signal from the thread (from the thread and not the thread object!) that would be caught by a slot in the widget.


So in setCurrentImageIpl() I emit a SIGNAL to a SLOT, the SLOT will do updateGL() for me.
This is wrong. You are emitting a signal on behalf of the widget from a worker thread. Qt checks which thread owns the sending and receiving objects, sees that it is the GUI thread, so makes a direct function call to updateGL() from the worker thread which is wrong and will cause segmentation faults sooner or later.



During displaying the first few frames that grasped by camera, my program crashes.
That's exactly what I mean :)

stella1016
25th July 2008, 19:29
This is bad. You can't access widgets from other threads and I can't stress that more. You should have emitted a signal from the thread (from the thread and not the thread object!) that would be caught by a slot in the widget.


So in setCurrentImageIpl() I emit a SIGNAL to a SLOT, the SLOT will do updateGL() for me.
This is wrong. You are emitting a signal on behalf of the widget from a worker thread. Qt checks which thread owns the sending and receiving objects, sees that it is the GUI thread, so makes a direct function call to updateGL() from the worker thread which is wrong and will cause segmentation faults sooner or later.



That's exactly what I mean :)

Thanks for your replay.
I don't fully understand what you mean...So how can I make things right?

wysota
25th July 2008, 20:48
Read about signals and multithreading, that's for a start. Then you need to make sure that:
1. you don't access any widget method from non-GUI thread directly
2. queued connections are used for signal-slot connections between threads (and I don't mean passing the optional argument to connect() but to make sure Qt will choose queued connections by itself).