PDA

View Full Version : change QWidget from QThread classes



radeberger
28th May 2010, 07:27
Hi everybody!

I have a QMainWindow application with some QThread classes. I'm changing the GUI widgets from QThread objects and partially it works properly.

if I have only one instance of my custom class (it is Qthread and this one makes instances of other QThread classes with QTcpServer/socket/ QUdpSocket) and I change the GUI widgets from these it works properly. For a second instance it works as well but for a third instance it works bad. What I saw is, the widgets stop updating and if a minimized the GUI window and after that I maximize the window again the widgets are changing and after a while it crases...

So I read that you can only change GUI widgets from the main thread but I'm doing it from other thread and it seems to be not so bad...

what can you recommend me? do you know why I have these crashes to update the gui? do I have one global mutex for all classes in order to update the gui?

Thanks in advance

borisbn
28th May 2010, 08:28
You cannot update gui directly from QThread's functions. You should emit signals in threading functions, that should be connected to slots in a gui class.
for example:


class MyThread : public QThread
{
Q_OBJECT
...
signals:
void updateLabel( QString str );
};

void MyThread::run()
{
...
emit updateLabel( "the text" );
}

class MyGuiClass : public QMainWindow
{
Q_OBJECT
...
public slots:
void onUpdateLabel( QString str );
};

MyGuiClass::MyGuiClass( )
{
...
m_thread = new MyThread();
connect( m_thread, SIGNAL( updateLabel( QString ) ), SLOT( onUpdateLabel( QString ) ) );
}

void MyGuiClass::onUpdateLabel( QString str )
{
ui.label->setText( str );
}

radeberger
28th May 2010, 08:57
Thanks borisbn, I'll try you proposal.

Do I need something like a buffer to store the data in case of quick updates?

Thanks!

radeberger
28th May 2010, 10:13
Hi again,

I have some problems to transmit the signal between thread. I used your example to programme my signals/slots but the problem is that I can't get the signals.

The structure that I have is:

MyGUIClass:
instance of QTthread1

radeberger
28th May 2010, 10:19
sorry! I struggled with my keyboard!

so, I have this structure in my programm:

MyGUIClass:
instance of QThread1

QThread1:
instance of QThread2 and QThread3

I need to send signals from Qthread2 to Qthread1 and the from Qthread1 to MyGUIClass (first GUI update)
and then I need a signal from QThread1 to MyGUIClass ( second UI update)

So I did it, I'm testing now and I don's get the signal from QThread2 to 1, so I can't see anything in the GUI

I tried to use the flag Qt::DirectConnection in the connect but It doesnn't works

do you have any ideas?

thanks!

borisbn
29th May 2010, 06:29
1. (about buffer between thread and gui) signal's parameter are buffers (e.g. copies). But if you need a huge number of data to transmit from thread to gui, you can alloc them by new and pass a pointer to gui. Then gui should proceed data, and delete this pointer
2. (about transmitting signal from "child of child" to parent) you can create a signal in thread2 and thread3 classes and connect them to signal of a thread1 object


class Thread2 : public QThread
{
...
signals:
void thread2_signal(QString str);
};

Thread1::Thread1()
{
thread2 = new Thread2();
connect( thread2, SIGNAL(thread2_signal(QString)), SIGNAL(thread1_signal(QString));
}

radeberger
30th May 2010, 13:42
thanks for your help borisbn,

I've tried to transmit a signal from "child of child to parent" and I didn't manage to catch the signal.

I did this:

thread 1 --> parent
thread 2 --> child1
thread 3 --> child2 (child of child1)

in thread2 I connect thread3_signal to thread2_signal :



connect( thread3, SIGNAL(thread3_signal(QString)), SIGNAL(thread2_signal(QString));


in thread1 I connected the signal from thread2 to the slot in thread 1, that will be update the GUI:



connect( thread2, SIGNAL(thread2_signal(QString)), SLOT(thread1_slotl(QString));


this way I don't get the signal in thread1

do you have some ideas?

thanks in advance!!

borisbn
30th May 2010, 14:47
It's not easy to understand a problem by pieces of code. If you'll archive your project and attach it to the next post, I'll try to assist.
P.S. Try to create several signals/slots in one class e.g. main gui class. Connect them in a way you want and see, what will happen (or not happen :) )

radeberger
30th May 2010, 16:31
ok, this is my code:

main thread:


// function for button start

void mainThread::clickedStart(){
obj2 = new seconThread(params);
connect( obj2 , SIGNAL( update1( int, int ) ), SLOT( onUpdate1( int, int ) ) );
connect( obj2 , SIGNAL( update2( int, int ) ), SLOT( onUpdate2( int, int ) ) );
obj2 ->start();
}

// slot update1
void mainThread::onUpdate1(int a, int b){

ui.showtrace1->setText(QString("%1").arg(a));
ui.showtrace2->setText(QString("%1").arg(b));

}

// slot update2
void mainThread::onUpdate2(int a, int b){

ui.showtrace3>setText(QString("%1").arg(a));
ui.showtrace4->setText(QString("%1").arg(b));
}


second thread:



void seconThread::run(){

obj3 = new thirdThread(params);
connect( obj3 , SIGNAL( update3(int, int) ), SIGNAL(update1 (int, int) ) );
connect( obj3 , SIGNAL( update4(int, int) ), SIGNAL( update2(int, int) ) );
obj3 ->start();
}



third thread:




void thirdThread::run(){

while(control){
// some prrcess
emit update3( a, b);
emit update4( c, d);

}
}


The point is, I can't get the signals update1 and update2, I've tried this way (connect signal to signal in the second thread)and to send a signal from thread3 to thread2 in a slot and then to send a signal from this to the main thread but it didn't work.

P.S. I tried to make the connection queued too, but no luck!!

Thanks in advance!!

radeberger
30th May 2010, 16:42
I have it!!

my problem was with one slot function. It takes two params and I gave only one!

I noticed it when I was posting the last thread,

sorry for the trouble and thanks to Borisbn, you are right, it's better to post the code ;)

Thank you very much!

radeberger
30th May 2010, 16:59
so, now another problem, it works finel if I only have one instance of secondThread in the main thread but if I have two instances, I don't get the signals anymore.

what happens?

borisbn
30th May 2010, 18:45
Take a look in a output window of your debugger. Qt writes thereany problem occured while connecting signals/slots and emitting signals. In your case Qt said you about wrong number of parameters (change back and make sure)

radeberger
30th May 2010, 19:45
thanks borisbn, it helped me!