PDA

View Full Version : State Machine Framework haging the UI when using it on a Qthread



acano
6th October 2011, 12:11
Hi everyone,

I am using the State Machine framework to simulate the behavious of some animations.

The problem is that when I do so the UI hangs.


Could someone help?, please.

Here is my code:


#include "frogs.h"


frogs::frogs(QWidget *parent) :
QThread()
{
imagenrana = new QLabel(parent);

imagenrana->setPixmap(QPixmap(":frog1.png"));
imagenrana->move(50, 50);
imagenrana->show();
imagenrana->setAttribute(Qt::WA_DeleteOnClose);

// imagenrana->close();

automataRana =new QStateMachine();

QState * sReposo = new QState();
QState * sMorir = new QState();
QState * sDescansar = new QState();

automataRana->addState(sReposo);
automataRana->addState(sMorir);
automataRana->addState(sDescansar);
sReposo->addTransition(this, SIGNAL(tocada()), sMorir);
sReposo->addTransition(this, SIGNAL(cansada()), sDescansar);

connect(sReposo, SIGNAL(entered()), this, SLOT (esperar()));
connect(sDescansar, SIGNAL(entered()), this, SLOT (esconder()));
connect(sMorir, SIGNAL(entered()), this, SLOT (morir()));




automataRana->setInitialState(sReposo);



}


void frogs::run() {
automataRana->start();
// QThread::sleep(5);
// imagenrana->close();
}

void frogs::esperar() {
QThread::sleep(5);
// for (int i=0;i<5;i++) {
// sleep(1);
// this->exec();
// }
emit cansada() ;
}




void frogs::esconder() {
imagenrana->close();
this->~QThread();
}

void frogs::morir() {
this->~QThread();
}



Here is how I call the thread:




frogs * rana = new frogs(background);

rana->start();

wysota
7th October 2011, 20:48
Do the transitions involve some animations or property changes of some QObjects? It seems "imagenrana" is a widget, you can't access those from within threads. Furthermore your state machine lives in the main thread and not in the thread you create thus you can't access it from the thread either.

acano
8th October 2011, 07:29
Thanks for your useful help wysota.


Furthermore your state machine lives in the main thread and not in the thread you create thus you can't access it from the thread either.

Can I make my state machine to live in the thread I create?

wysota
8th October 2011, 08:36
Yes, create it in the run() method of your thread. or use QObject::moveToThread().

acano
11th October 2011, 10:57
I tried to do it by creating the State Machine in the run() method. But it is still not working: the slot SLOT (esperar()) is never executed.

Do you have some idea about why is it happening.

Thaks again!!



#include "frogs.h"


frogs::frogs(QWidget *parent) :
QThread()
{


}


void frogs::run() {

automataRana =new QStateMachine();

QState * sReposo = new QState();
QState * sMorir = new QState();
QState * sDescansar = new QState();

automataRana->addState(sReposo);
automataRana->addState(sMorir);
automataRana->addState(sDescansar);
sReposo->addTransition(this, SIGNAL(tocada()), sMorir);
sReposo->addTransition(this, SIGNAL(cansada()), sDescansar);



automataRana->setInitialState(sReposo);


connect(sReposo, SIGNAL(entered()), this, SLOT (esperar()));
connect(sDescansar, SIGNAL(entered()), this, SLOT (esconder()));
connect(sMorir, SIGNAL(entered()), this, SLOT (morir()));
connect(this, SIGNAL(cansada()), this, SLOT (esperar()));

automataRana->start();

// imagenrana->close();
}

void frogs::esperar() {
qDebug("He entrado en Esperar");
QThread::sleep(5);
emit cansada() ;
}




void frogs::esconder() {
// imagenrana->close();
}

void frogs::morir() {
// imagenrana->close();
}

wysota
11th October 2011, 12:54
Why should the slot be executed? Apparently you never enter the sReposo state.

acano
11th October 2011, 13:44
Why should the slot be executed? Apparently you never enter the sReposo state.

Actually yes, it is the initial state:



automataRana->setInitialState(sReposo);

wysota
11th October 2011, 14:26
If it is the initial state then you never enter it. You are already in it when the machine starts running.

acano
11th October 2011, 14:33
If it is the initial state then you never enter it. You are already in it when the machine starts running.

Believe me. It does not work.

I emited SIGNAL(tocada()) and SLOT (morir()) is not executed.

There is still something wrong in my code.

Anyway, thank you very much for your help.

wysota
11th October 2011, 14:37
I think the problem is that your run() returns right after the machine is started and the thread stops running. Try calling exec() at the end of your run() method.

acano
11th October 2011, 14:52
I think the problem is that your run() returns right after the machine is started and the thread stops running. Try calling exec() at the end of your run() method.

May be that is the reason.

I tried calling exec() at then end, but then the main Thread is stalled again.

Do you think that trying with QThread::wait() is a good idea?

wysota
11th October 2011, 14:53
Then maybe your thread is not running at all? You are starting it with start() and not run(), right?

acano
11th October 2011, 15:01
Then maybe your thread is not running at all? You are starting it with start() and not run(), right?

Yes, I am starting with start(). Is there something wrong with it?

wysota
11th October 2011, 15:08
It would be advised if you posted your complete code related to the thread and your main() function.

acano
13th October 2011, 15:24
the problem is finally soved.

The code is like:


frogs * rana = new frogs(background);
rana->moveToThread(rana);
rana->start();


Thank you very much for your help wysota.

Best Regards,

A. Cano