PDA

View Full Version : Problem with QLabel and setText



jambrek
30th October 2007, 14:58
I have 2 threads. One main thread and one created thread. I'm creating thread in constructor of class and pass it "this" pointer. In a thread I'm accessing to class via pointer and call a public method (function) of this class. In this method I'm calling setText method in QLabel widget. It does not work. Program is crashed. When I use setText in another method of this class it works. I've tried another methods of QLabel and some works, and some doesn't. Any method who has "set" in its name doesn't work, and clear too, but methods like adjustSize() works. I tried another widgets and problem is same.

I've created thread with winapi CreateThread function, and name of class is MainWin.

Code of created thread:

DWORD WINAPI ItemReceiver(LPVOID param)
{
MainWin *mwin = (MainWin*)param;
while(true)
{
WaitForSingleObject(SEM,INFINITE);
mwin->ReceiveItem();
}

return 0;
}

Way of calling setText function:

lblCommand->setText("Command: ");

lblCommand is pointer to QLabel.

wysota
30th October 2007, 15:05
You can't access QObject subclasses from within a worker thread.

high_flyer
30th October 2007, 15:11
Is this a Qt application or just winapi / MFC /other application?
If this is a Qt application then why not use QThread?

Also, the way you are doing it is not good.
Either use an event or a queued signal to update the label.
OR
If you really have to access the variable from a another thread use a QMutex.

Also, please make sure your read the docs about multi threading with Qt.
Qt makes multi threading much easier then MFC/WinApi.

jambrek
30th October 2007, 15:18
This is a QT application. I've used winapi because it's similar to me. I've never used QThread, but I will try.

Thanks

jambrek
30th October 2007, 15:34
"wysota: You can't access QObject subclasses from within a worker thread."

Sometimes I can:

lblCommand->adjustSize(); //pass
lblCommand->childAt(20,20); //pass
lblCommand->setVisible(true); //crash

jpn
30th October 2007, 16:38
In other words, you MUST NOT touch GUI from a worker thread.

QObject Reentrancy (http://doc.trolltech.com/4.3/threads.html#qobject-reentrancy):

Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread. As noted earlier, QCoreApplication::exec() must also be called from that thread.

In practice, the impossibility of using GUI classes in other threads than the main thread can easily be worked around by putting time-consuming operations in a separate worker thread and displaying the results on screen in the main thread when the worker thread is finished. This is the approach used for implementing the Mandelbrot (http://doc.trolltech.com/4.3/threads-mandelbrot.html) and the Blocking Fortune Client (http://doc.trolltech.com/4.3/network-blockingfortuneclient.html) example.

wysota
30th October 2007, 21:35
Sometimes I can:

lblCommand->adjustSize(); //pass
lblCommand->childAt(20,20); //pass
lblCommand->setVisible(true); //crash

Try running those in a loop and do something else with the GUI in between (like move the window with your mouse). While childAt() might suceed as it doesn't touch much of the structures, adjustSize() is bound to fail eventually. setVisible() is an obvious candidate for an immediate crash though :)

jambrek
31st October 2007, 16:02
Problem is solved by using signal and slots. I've created signals which connected to setText slots for each label. It works.

Thanks a lot.