I'm trying to learn about SCXML (http://www.w3.org/TR/scxml/) and the Qt implementation of it (http://http://doc.trolltech.com/solu...ine/scxml.html).
I'm experimenting with the simplest state machine I can think of which has 2 states, s1, the initial state and s2. A transition from s1 to s2 occurs when some value exceeds a number.
I've written a small Qt app that displays a button that says "hello". When the button is pushed, nClicked is incremented. A transition to state s2 should occur when nClicked > 2 and then the button label changes to "goodbye". I have forced a transition if nClicked > 4.
I have been unable to get the transition to occur automatically. It seems that the value of nClicked is not getting to the script engine to be evaluated. When the transition is forced, the label does change and in fact if I use anything other than myClass.nClicked in the cond parameter in the scxml file, I get an error message about not being able to find the variable when the event is triggered so it appears that I have set the property correctly but the nClicked that the script knows about is not the same as the nClicked that it getting incremented. I'm obviously missing something.
Thanks,
Steve
I have attached my test program and data (and the qscxml.cpp and .h file)
I am running this on a CentOS 6.2 machine and I used
$ qmake-qt4 -project
$ qmake
Edit the generated Makefile to add /usr/include/QtScript to the INCPATH and -lQtScript to LIBS.
$ gmake
junk.scxml:
<?xml version='1.0' encoding='UTF-8'?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s1">
<state id="s1">
<transition event="t" cond="myClass.nClicked > 2" target="s2"/>
</state>
<state id="s2">
</state>
</scxml>
<?xml version='1.0' encoding='UTF-8'?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s1">
<state id="s1">
<transition event="t" cond="myClass.nClicked > 2" target="s2"/>
</state>
<state id="s2">
</state>
</scxml>
To copy to clipboard, switch view to plain text mode
class.h:
#ifndef MYCLASS_H
#define MYCLASS_H
#include <iostream>
#include <QWidget>
#include <QPushButton>
#include <QScriptEngine>
#include <QString>
#include "qscxml.h"
using namespace std;
{
Q_OBJECT
public:
int nClicked;
QScxml* sm;
QScriptValue sv;
public slots:
void addClicks();
void changeLabel() { pb->setText("Goodbye"); }
private:
const QString getCurrentState
() const;
void printStateName() const;
};
#endif
#ifndef MYCLASS_H
#define MYCLASS_H
#include <iostream>
#include <QWidget>
#include <QPushButton>
#include <QScriptEngine>
#include <QString>
#include "qscxml.h"
using namespace std;
class MyClass : public QWidget
{
Q_OBJECT
public:
MyClass(QWidget* parent = 0);
int nClicked;
QScxml* sm;
QPushButton* pb;
QScriptValue sv;
public slots:
void addClicks();
void changeLabel() { pb->setText("Goodbye"); }
private:
const QString getCurrentState() const;
void printStateName() const;
};
#endif
To copy to clipboard, switch view to plain text mode
main.cpp:
#include <iostream>
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QObject>
#include <QScriptEngine>
#include <QString>
#include "qscxml.h"
#include "class.h"
using namespace std;
{
sm = QScxml::load("./junk.scxml");
sm->registerObject(this, "myClass", true);
sv = sm->scriptEngine()->newQObject(this);
sm->scriptEngine()->globalObject().setProperty("myClass", sv);
connect(pb, SIGNAL(clicked()), this, SLOT(addClicks()));
connect(sm,
SIGNAL(eventTriggered
(QString)),
this,
SLOT(changeLabel
()));
sm->start();
}
void MyClass::addClicks()
{
nClicked++;
cout << "nclicked = " << nClicked << endl;
if (nClicked > 4)
sm->postNamedEvent("t");
}
int main(int argc, char* argv[])
{
MyClass* w = new MyClass;
w->show();
return app.exec();
}
#include <iostream>
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QObject>
#include <QScriptEngine>
#include <QString>
#include "qscxml.h"
#include "class.h"
using namespace std;
MyClass::MyClass(QWidget* parent)
: QWidget(parent), nClicked(0)
{
pb = new QPushButton("Hello", this);
sm = QScxml::load("./junk.scxml");
sm->registerObject(this, "myClass", true);
sv = sm->scriptEngine()->newQObject(this);
sm->scriptEngine()->globalObject().setProperty("myClass", sv);
connect(pb, SIGNAL(clicked()), this, SLOT(addClicks()));
connect(sm, SIGNAL(eventTriggered(QString)), this, SLOT(changeLabel()));
sm->start();
}
void MyClass::addClicks()
{
nClicked++;
cout << "nclicked = " << nClicked << endl;
if (nClicked > 4)
sm->postNamedEvent("t");
}
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MyClass* w = new MyClass;
w->show();
return app.exec();
}
To copy to clipboard, switch view to plain text mode
Bookmarks