PDA

View Full Version : QState::addTransition + signal with an integer as a parameter



lamb
4th September 2012, 14:11
Hi,

it is possible to write a signal function with parameter. Example:


class MyClass
{
public:

void sendTheSignal(void)
{
//int i = {1, 2, 3}
emit signalPower(i);
}
...
signals:
signalPower(int);
};


But how can I send such a signal to QState::addTransition:



MyClass* pMyClass = new MyClass();
QState* pMyState1 = new QState(pRootState);
QState* pMyState2 = new QState(pRootState);
QState* pMyState3 = new QState(pRootState);

pMyState1->addTransition(pMyClass , SIGNAL(signalPower(int)), pMyState2);
pMyState1->addTransition(pMyClass , SIGNAL(signalPower(int)), pMyState3);

pMyState2->addTransition(pMyClass , SIGNAL(signalPower(int)), pMyState1);
pMyState2->addTransition(pMyClass , SIGNAL(signalPower(int)), pMyState3);

pMyState3->addTransition(pMyClass , SIGNAL(signalPower(int)), pMyState1);
pMyState3->addTransition(pMyClass , SIGNAL(signalPower(int)), pMyState3);


This doesn't work. I want to enter the states depending on the value in the signal.

Thank you,

- the lamb

lamb
4th September 2012, 23:14
I found a solution:

MainWindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QSignalTransition>
#include <QStateMachine>


class QStateMachine;

class MyClass : public QObject
{
Q_OBJECT
signals:

void signalWithParameter(int value);

public:
void sendSignal(int i)
{
qDebug() << "Send i = " << i;
emit signalWithParameter(i);
}
};

class MySignalTransition : public QSignalTransition
{
public:
MySignalTransition(MyClass *myClass, int i)
: QSignalTransition(myClass, SIGNAL(signalWithParameter(int)))
{
m_i = i;
qDebug() << "Ctor " << m_i;
}
protected:
virtual bool eventTest(QEvent *e)
{
qDebug() << "###########################";

if (!QSignalTransition::eventTest(e))
return false;
QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e);
int test = se->arguments().at(0).toInt();
qDebug() << "m_i: " << m_i << " test: " << test;
qDebug() << "************************";
return (test == m_i);
}

virtual void onTransition(QEvent *e)
{
QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e);
int x = se->arguments().at(0).toInt();
qDebug() << "x = " << x;
}


private:
int m_i;
};


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

public slots:
void slotSendSignal1(void);
void slotSendSignal2(void);
void slotSendSignal3(void);

void slotReceiveSignal(int i);

private:
Ui::MainWindow *ui;

MyClass* m_pMyClass;

QStateMachine* m_pMachine;

QList<MySignalTransition*> m_pMySignalTransitions;
};

#endif // MAINWINDOW_H


MainWindow.cpp


#include "MainWindow.h"
#include "ui_MainWindow.h"

#include <QFinalState>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

m_pMyClass = new MyClass();

connect(ui->pushButton_1, SIGNAL(clicked()), this, SLOT(slotSendSignal1()));
connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(slotSendSignal2()));
connect(ui->pushButton_3, SIGNAL(clicked()), this, SLOT(slotSendSignal3()));

connect(m_pMyClass, SIGNAL(signalWithParameter(int)), this, SLOT(slotReceiveSignal(int)));

m_pMachine = new QStateMachine(this);

QState *s1 = new QState();
QState *s11 = new QState(s1);
QState *s12 = new QState(s1);
QState *s13 = new QState(s1);

m_pMySignalTransitions.push_back(new MySignalTransition(m_pMyClass, 0));
m_pMySignalTransitions.push_back(new MySignalTransition(m_pMyClass, 1));
m_pMySignalTransitions.push_back(new MySignalTransition(m_pMyClass, 2));
m_pMySignalTransitions.push_back(new MySignalTransition(m_pMyClass, 0));
m_pMySignalTransitions.push_back(new MySignalTransition(m_pMyClass, 1));
m_pMySignalTransitions.push_back(new MySignalTransition(m_pMyClass, 2));

m_pMySignalTransitions.at(0)->setTargetState(s11);
m_pMySignalTransitions.at(1)->setTargetState(s12);
m_pMySignalTransitions.at(2)->setTargetState(s13);
m_pMySignalTransitions.at(3)->setTargetState(s11);
m_pMySignalTransitions.at(4)->setTargetState(s12);
m_pMySignalTransitions.at(5)->setTargetState(s13);

s1->setInitialState(s11);

s11->addTransition(m_pMySignalTransitions.at(1));
s11->addTransition(m_pMySignalTransitions.at(2));

s12->addTransition(m_pMySignalTransitions.at(0));
s12->addTransition(m_pMySignalTransitions.at(5));

s13->addTransition(m_pMySignalTransitions.at(3));
s13->addTransition(m_pMySignalTransitions.at(4));

s11->assignProperty(ui->labelCurrentState, "text", "In state s11");

s12->assignProperty(ui->labelCurrentState, "text", "In state s12");

s13->assignProperty(ui->labelCurrentState, "text", "In state s13");

m_pMachine->addState(s1);

m_pMachine->setInitialState(s1);

m_pMachine->start();
}

MainWindow::~MainWindow()
{
delete ui;

foreach(MySignalTransition* mst, m_pMySignalTransitions)
{
delete mst;
}

delete m_pMyClass;

delete m_pMachine;
}


void MainWindow::slotSendSignal1()
{
m_pMyClass->sendSignal(0);
}


void MainWindow::slotSendSignal2()
{
m_pMyClass->sendSignal(1);
}


void MainWindow::slotSendSignal3()
{
m_pMyClass->sendSignal(2);
}


void MainWindow::slotReceiveSignal(int i)
{
qDebug() << "Signal received " << i;
}


But this is rather complex. Hay anybody a easier solution?

Thanks,

- The lamb