views:

168

answers:

3

I am trying to build an QT State Maschine. I have some States, and for those States i need Transition that alter the Graphics on my gui. The Problem i having and the only reason i am asking, i am Stuck and Point 1.

The compiler cant identifie the QTEventTransition. I have QT 4.6 wroking with QT Creator on Windows. The compiler does not find Header #include < QtEventTransition >

This is what i did i never did this bevor but i think it should be correct, I have A Header File where i have my Transitions Declareted like this:

       class validateBoatTransition : public QtEventTransition
    {
    public:
        validateBoatTransition(Widget *widget,ServerSkeleton* server);

    protected:
       bool eventTest(QEvent *e);
       void onTransition(QEvent *);

    private:
       Chart* ourChart;
       Message current;
       BarelySocket* myBarelySocket;
    };

Than i have my Cpp File where i have this:

validateBoatTransition::validateBoatTransition(Widget *widget,ServerSkeleton* server)
{


}


void validateBoatTransition::onTransition(QEvent *e)
{
    /*
  My Logik should go here
*/
}

What i want is that if the Transition is activated by an Button (clicked) it should fire this transition!

I searched the net, but cant find an solution. Can i do that? I should i think.

Yours Thomas

A: 

Maybe you should take a look to signals/slot mechanism. I think this is what you need to achieve what you want.

Make your onTransition function a slot instead of an event handler and connect it to the signal clicked of the button.

class validateBoatTransition : public QtEventTransition { ...

public slots:
    void onTransition();

...

}

Somewhere in your code, connect the button to the slot:

QObject::connect(myButton, signal(clicked()), myValidateBoatTransition, slot(onTransition());

Each time the button will be clicked the execution will go through the onTransition function.

Patrice Bernassola
This is what i had. But it got to messy. I dont have a Button. This is a Part of my Programm.
Thomas
A: 

I think you're trying to use wrong classes/mechanisms to achieve your goals. If I understand you correctly, you have some GUI and after clicking some button you want to validate some stuff and if this validation is successful the state machine should change it's state. I'd write it this way:

Create some class to handle validation:

class BoatValidator : public QObject
{
Q_OBJECT

// boring stuff like constructor, etc.

public slots:
    void validate() 
    {
        if ( /*your validation logic goes here*/ ) {
            emit boatTransition();
        }
    }

signals:
    void boatTransition(); // emitted if validation is succesful        
};

Then you connect your QPushButton::clicked() to BoatValidator::validate() and use BoatValidator::boatTransition() signal to drive the state machine:

QStateMachine machine;
QState *state1 = new QState(&machine);
QState *state2 = new QState(&machine);

// more state machine setup

// connect validator and button
QPushButton button;
BoatValidator validator;
connect(&button, SIGNAL(clicked()), &validator, SLOT(validate()));

// use validator to change states
state1->addTransition(&validator, SIGNAL(boatTransition()), state2);

Generally I'd use signal to drive state machine, unless some transitions are obviously event driven (for example some QEvent::Enter/QEvent::Leave on GUI widgets, etc.).

chalup
Thank you, your Idea worked fine. But still now the code looks as messy as before. And if the transition is not changing the state its looks like a waste of code
Thomas
Yes, the code utilizing QStateMachine might get messy sometimes and I don't have a tested solution that would make it clearer. I don't understand your comment about "waste of code" in the "transition" - what are you talking about?
chalup
A: 

What i wanted to do is build a Qt State Machine. The Problem was that i could not trigger my own Transitions (let alone with my own Events). The answers given are good but would lead to a messy code. Why should i use a QT State Machine if i could not use the QT Transitions? The First Problem above is solved, if you create a new Project. QT Creater is very annoying. But here now my solution , may it help others.

First my State:

class ServerState : public QState
{
    Q_OBJECT

public:
    ServerState(QPushButton * pushButton);
    ~ServerState();

public slots:
    void buttonWasClicked();

protected:
    void onEntry(QEvent *e);
    void onExit(QEvent *e);

private:
    QPushButton * pushButton;
};

Normal, but you see i added an Slot. This slot enables me to connect a bottom signal or a Widget Mouse Press Signal to it !
Like this:

QStateMachine *machine = new QStateMachine(this);
ServerState *s1 = new ServerState(connectButton);
connect(connectButton, SIGNAL(clicked()), s1, SLOT(buttonWasClicked()));
machine->addState(s1);
s1->addTransition(connectTransition);

all i needed to to is now fire a declared Event like this one :

#define RegisterToServerEventIndex User+5
class ConnectToServerEvent : public QEvent
{
public:
    ConnectToServerEvent() : QEvent(QEvent::Type(QEvent::ConnectToServerEventIndex))
    {}
};

when the slot was called:

void ServerState::buttonWasClicked()
{
    this->machine()->postEvent(new ConnectToServerEvent());
    qDebug("ServerState::buttonWasClicked");
}

The QT State Machine would now call all the Transitions , link with this state:

ConnectToServerTransition::ConnectToServerTransition(QPushButton * pushButtonB,ServerSkeleton* serverSkeleton)
{
    this->pushButtonB = pushButtonB;
    this->pushButtonB->hide();
    this->serverSkeleton  = serverSkeleton;
    qDebug("ConnectToServerTransition::ConnectToServerTransition");
}

bool ConnectToServerTransition::eventTest(QEvent *e)
{
    return  (e->type() == QEvent::ConnectToServerEventIndex);
}

void ConnectToServerTransition::onTransition(QEvent *e)
{
    if (true ==  this->serverSkeleton->initalisieren())
    {
        this->pushButtonB->show();
    }else{
        qDebug("Conection to Server faild");
    }
    emit kill();
    return;
}

Whats so great that i dare to post? Well first you can link a Qt SM to a widget where a mouse press event , or somthing else, is called and process the raw data to a an level you need later in your program. All you then need to do is, to emit the singal:

void Widget::mousePressEvent(QMouseEvent *event){
    Coordinates current;
    current.line = 0;
    current.row = A;
    current.row = (Row) (event->x() / 30); // 30 = breite von einen Feld
    current.line = event->y() / 30; // 30 = länge von einen Feld
    emit this->clicked(current);
    return;
}

Then this enhenced information (current) is passed to the slot at my state, where i chose to call the correct transition that does the work. You could link more transitions to it, if you need it.

But most importend you dont need to reprogramm the Transition, a think i realy disliked.

Thank you for your help , i could not done it alone.

Thomas