[Qt-interest] please help me with this problem
Yifei Li
yifli at mtu.edu
Wed Dec 9 03:31:46 CET 2009
Scott,
Thank you for asking me to post a simple example, otherwise it would take me forever to figure out the problem :)
Here's a minimal example of what I'm trying to do. The thing that causes my problem is the line "w->wait()", removing that line makes my program work (I compiled the following src code in VS 2008).
It seems like calling w->wait() not only blocks the worker thread, but also the whole application, thus preventing the application from updating the displayed message. But I'm still not quite sure about this, do you have a better answer?
#include <QtGui/QApplication>
#include <QWidget>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QThread>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QPainterPath>
#include <QVBoxLayout>
class Worker : public QThread {
Q_OBJECT
signals:
void displayMessage(QString);
protected:
void run();
};
class Scene : public QGraphicsScene {
Q_OBJECT
public slots:
void setMessage(QString);
protected:
void drawForeground(QPainter*, const QRectF&);
private:
QString m_msg;
};
#include "main.moc"
void Worker::run()
{
sleep(5);
emit displayMessage("hello1");
sleep(2);
emit displayMessage("hello2");
sleep(2);
}
void Scene::setMessage(QString msg)
{
m_msg = msg;
update();
}
void Scene::drawForeground(QPainter* painter, const QRectF&)
{
QPainterPath msg;
msg.addText(5, height()-5, QApplication::font(), m_msg);
painter->setPen(QPen(QColor(Qt::black)));
painter->setBrush(QBrush(QColor(Qt::black)));
painter->drawPath(msg);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget* mainWidget = new QWidget;
Scene scene;
QGraphicsView view(&scene, mainWidget);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(&view);
mainWidget->setLayout(layout);
mainWidget->show();
Worker* w = new Worker;
QObject::connect(w, SIGNAL(displayMessage(QString)), &scene, SLOT(setMessage(QString)), Qt::DirectConnection);
w->start();
w->wait(); // !!TROUBLE MAKER!!
return a.exec();
}
----- Original Message -----
From: "Scott Aron Bloom" <Scott.Bloom at sabgroup.com>
To: "Yifei Li" <yifli at mtu.edu>
Cc: qt-interest at trolltech.com
Sent: Tuesday, December 8, 2009 4:28:31 PM GMT -05:00 US/Canada Eastern
Subject: RE: [Qt-interest] please help me with this problem
Yes...
Post a simple 1 file example showing the problem so we can see how you connected everything...
Scott
-----Original Message-----
From: Yifei Li [mailto:yifli at mtu.edu]
Sent: Tuesday, December 08, 2009 1:22 PM
To: Scott Aron Bloom
Cc: qt-interest at trolltech.com
Subject: Re: [Qt-interest] please help me with this problem
Scott,
You said "The problem is you are trying to change the GUI directly, from a non-gui thread...", however, I did not get errors like "QPixmap: It is not safe to use pixmaps outside the GUI thread"
I tried to create a QTimer (in gui thread) with a timeout of 500msec, and connect its timeout signal to QGraphicsScene::update. I can see QGraphicsScene::drawForeground is called repeatedly (coz I output the content of the message to a terminal whenever the scene is updated)
However, while the worker thread (which emits signals to set the message at intervals) is running, no message is output to the terminal. After the thread is finished, since the content of the message is already set to be 'hello2', 'hello2' starts to appear in the terminal again. So it seems like the execution of the worker thread prevents the main thread from processing events.
However, I also tried sending/posting custom events from the worker thread to the main thread, and I can see those custom events are handled while the worker thread is running
I'm totally confused now. Do you have any ideas? Thanks
Yifei
----- Original Message -----
From: "Scott Aron Bloom" <Scott.Bloom at sabgroup.com>
To: qt-interest at trolltech.com
Sent: Monday, December 7, 2009 11:21:30 PM GMT -05:00 US/Canada Eastern
Subject: Re: [Qt-interest] please help me with this problem
I would post a working minimal example.. 1 file that we can run and see the results....
Scott
-----Original Message-----
From: qt-interest-bounces at trolltech.com [mailto:qt-interest-bounces at trolltech.com] On Behalf Of Yifei Li
Sent: Monday, December 07, 2009 8:15 PM
To: qt-interest at trolltech.com
Subject: Re: [Qt-interest] please help me with this problem
Scott,
Here're some details:
// Worker Thread
void run()
{
plugin->exec(); // plugin is a QObject
}
// called after a plugin is loaded
// both plugin and scene live in the main thread
connect(plugin, SIGNAL(displayMessage(QString)), scene, SLOT(setMessage(QString)), Qt::DirectionConnection);
void setMessage(QString msg)
{
m_message = msg;
update();
}
Yifei
----- Original Message -----
From: "Scott Aron Bloom" <Scott.Bloom at sabgroup.com>
To: "Yifei Li" <yifli at mtu.edu>, qt-interest at trolltech.com
Sent: Monday, December 7, 2009 10:23:17 PM GMT -05:00 US/Canada Eastern
Subject: RE: [Qt-interest] please help me with this problem
The problem is you are trying to change the GUI directly, from a non-gui thread...
Make sure your GUI's event loop, is still active, and not in blocked state.. Without seeing how you have the threads connected, there is no way to tell what the problem is.
Scott
-----Original Message-----
From: qt-interest-bounces at trolltech.com [mailto:qt-interest-bounces at trolltech.com] On Behalf Of Yifei Li
Sent: Monday, December 07, 2009 6:40 PM
To: qt-interest at trolltech.com
Subject: Re: [Qt-interest] please help me with this problem
I use a variable to keep track of the current message to be displayed.
every time the signal displayMessage is emitted to a slot, that slot calls QGraphicsScene::update()
but I never see the first two messages show up
Yifei
----- Original Message -----
From: "程梁" <chengliang.soft at gmail.com>
To: qt-interest at trolltech.com
Sent: Monday, December 7, 2009 7:44:46 PM GMT -05:00 US/Canada Eastern
Subject: Re: [Qt-interest] please help me with this problem
I think it is because it is really paint but the later one draws over it.
That is the scene refresh by the new message.
2009/12/8 Yifei Li < yifli at mtu.edu >
Hi folks,
In my thread's run() method, signal displayMessage(QString) is emitted and the signal is connected to a slot setMessage(QString) in a QGraphicsScene object (using direct connection)
// run method looks like this:
void run()
{
sleep(2);
emit displayMessage("hello 1");
sleep(2);
emit displayMessage("hello 2");
sleep(2);
emit displayMessage("hello 3");
}
// Here is what setMessage(QString) looks like:
void setMessage(QString msg)
{
m_message = msg; // save the message
update();
}
The message is then displayed in drawForegound method
However, my problem is 'hello1' and 'hello2' don't show up at all, only 'hello3' does.
My guess is that update() queues the paint event and several paint events are merged into one due to optimization, so what should I do make those three messages displayed one after another?
Thanks
Yifei
_______________________________________________
Qt-interest mailing list
Qt-interest at trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-interest
--
Cheng Liang
from: chengliang.soft at gmail.com
_______________________________________________
Qt-interest mailing list
Qt-interest at trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-interest
_______________________________________________
Qt-interest mailing list
Qt-interest at trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-interest
_______________________________________________
Qt-interest mailing list
Qt-interest at trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-interest
_______________________________________________
Qt-interest mailing list
Qt-interest at trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-interest
More information about the Qt-interest-old
mailing list