Qt-jambi-interest Archive, April 2007
Thread issue with slots in Qt Jambi 1.0
Message 1 in thread
Dear all,
I want to update a widget from another thread. All was ok under Jambi
TP3 but with the beta 1.0, i have following error message :
Exception in thread "Thread-1" QObject used from outside its own thread...
As i seen in previous message in this list, i attempt to use queued
connections and to start an event loop in the thread but it doesn't
works (QThread.exec() method exists ?).
How can i do under Jambi 1.0 to update my widget from another thread ?
Regards,
Laurent.
My test code :
public class QtThreadTest extends QDialog {
private QLabel label = new QLabel("Hello world !!!");
private class MyThread extends QObject implements Runnable {
public QObject.Signal1<String> messageSignal = new
QObject.Signal1<String>();
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.messageSignal.emit("Hello world from MyThread !!!");
}
}
private void updateLabel(String message) {
this.label.setText(message);
}
public QtThreatTest() {
QGridLayout layout = new QGridLayout();
layout.addWidget(label);
this.setLayout(layout);
MyThread mt = new MyThread();
mt.messageSignal.connect(this, "updateLabel(String)",
ConnectionType.QueuedConnection);
QThread t = new QThread(mt);
t.start();
System.out.println("Thead running...");
}
public static void main(final String[] args) {
QApplication.initialize(args);
new QtThreadTest().show();
QApplication.exec();
}
}
Message 2 in thread
Laurent Jourdren wrote:
> Dear all,
>
> I want to update a widget from another thread. All was ok under Jambi
>
TP3 but with the beta 1.0, i have following error message :
>
> Exception in thread "Thread-1" QObject used from outside its own
> thread...
>
>
> As i seen in previous message in this list, i attempt to use queued
connections and to start an event loop in the thread but it doesn't
works (QThread.exec() method exists ?).
>
> How can i do under Jambi 1.0 to update my widget from another thread ?
Hi Laurent,
If you look at the stack trace for the exception you see that we are
making a call to signalsBlocked() in QObject from the emit call. Hence,
the owner of messageSignal, the MyThread instance, is being accessed
from the wrong thread. Since the thread instance is being used from the
other thread it needs to be moved to that thread. You fix this by adding
a call to mt.moveToThread(t), just after creating the thread, like this:
QThread t = new QThread(mt);
mt.moveToThread(t);
t.start();
Please note that when doing threading like this, only the _receiving_
object needs to be in an thread with a running event loop. GUI objects,
like your QLabel in this case is in the main thread which runs the GUI
event loop (QApplication.exec()) so you _do_not_ need to run an
additional event loop in this case.
If you need to do queued connections to an object in a non-GUI thread,
then you need to run an event loop. This is done by doing
QEventLoop eventLoop = new QEventLoop();
eventLoop.exec();
An alternative way of updating the GUI from other threads is to make use
of the QApplication.invokeLater() mechanism, like this:
QApplication.invokeLater(new Runnable() {
public void run() {
label.setText("...");
}
});
Another option is subclass QSignalEmitter directly and avoid the whole
QObject/thread issue ;-)
best regards,
Gunnar
Message 3 in thread
Hi Gunnar,
Now, it's works, thanks for all your help.
best regards,
Laurent.
2007/4/17, Gunnar Sletta <gunnar@xxxxxxxxxxxxx>:
>
> Laurent Jourdren wrote:
> > Dear all,
> >
> > I want to update a widget from another thread. All was ok under Jambi
> >
> TP3 but with the beta 1.0, i have following error message :
> >
> > Exception in thread "Thread-1" QObject used from outside its own
> > thread...
> >
> >
> > As i seen in previous message in this list, i attempt to use queued
> connections and to start an event loop in the thread but it doesn't
> works (QThread.exec() method exists ?).
> >
> > How can i do under Jambi 1.0 to update my widget from another thread ?
>
> Hi Laurent,
>
> If you look at the stack trace for the exception you see that we are
> making a call to signalsBlocked() in QObject from the emit call. Hence,
> the owner of messageSignal, the MyThread instance, is being accessed
> from the wrong thread. Since the thread instance is being used from the
> other thread it needs to be moved to that thread. You fix this by adding
> a call to mt.moveToThread(t), just after creating the thread, like this:
>
> QThread t = new QThread(mt);
> mt.moveToThread(t);
> t.start();
>
> Please note that when doing threading like this, only the _receiving_
> object needs to be in an thread with a running event loop. GUI objects,
> like your QLabel in this case is in the main thread which runs the GUI
> event loop (QApplication.exec()) so you _do_not_ need to run an
> additional event loop in this case.
>
> If you need to do queued connections to an object in a non-GUI thread,
> then you need to run an event loop. This is done by doing
>
> QEventLoop eventLoop = new QEventLoop();
> eventLoop.exec();
>
> An alternative way of updating the GUI from other threads is to make use
> of the QApplication.invokeLater() mechanism, like this:
>
> QApplication.invokeLater(new Runnable() {
> public void run() {
> label.setText("...");
> }
> });
>
> Another option is subclass QSignalEmitter directly and avoid the whole
> QObject/thread issue ;-)
>
> best regards,
> Gunnar
>
>
>