2010-04-07 19 views
1

J'essaye de construire une machine d'état QT. J'ai quelques états, et pour ces états j'ai besoin de Transition qui modifie les graphiques sur mon gui. Le problème que j'ai et la seule raison pour laquelle je demande, je suis coincé et le point 1.Implémentation QT EventTransition

Le compilateur ne peut pas identifier le QTEventTransition. J'ai QT 4.6 woking avec QT Creator sur Windows. Le compilateur ne trouve pas en-tête #include < QtEventTransition>

C'est ce que je je n'ai jamais fait cela bevor mais je pense qu'il devrait être correct, je dispose d'un fichier d'en-tête où j'ai mon Transitions Declareted comme ceci:

 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; 
    }; 

que moi mon Cpp fichier où j'ai ceci:

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


} 


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

ce que je veux est que si la transition est activé par un bouton (clic), il devrait tirer cette transition! J'ai cherché sur le net, mais ne peux pas trouver une solution.

Puis-je faire cela? Je devrais je pense.

Vôtre Thomas

Répondre

0

Ce que je voulais faire est de construire une machine d'état Qt. Le problème était que je ne pouvais pas déclencher mes propres transitions (et encore moins avec mes propres événements).Les réponses données sont bonnes mais conduiraient à un code désordonné. Pourquoi devrais-je utiliser une machine d'état QT si je ne pouvais pas utiliser les transitions QT? Le premier problème ci-dessus est résolu, si vous créez un nouveau projet. QT Creater est très ennuyeux. Mais voici maintenant ma solution, qu'elle aide les autres.

D'abord mon État:

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, mais vous voyez que j'ajouté un emplacement. Cette fente me permet de connecter un signal de fond ou un Widget Mouse Press Signal à celui-ci!
Comme ceci:

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

tout ce que je devais à feu est-il maintenant un événement déclaré comme celui-ci:

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

lorsque la fente a été appelée:

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

L'État QT La machine appelle maintenant toutes les transitions, lien avec cet état:

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; 
} 

Qu'est-ce si bon que j'ose poster? Eh bien d'abord vous pouvez lier un Qt SM à un widget où un événement de presse de la souris, ou quelque chose d'autre, est appelé et traiter les données brutes à un niveau dont vous avez besoin plus tard dans votre programme. Tout ce que vous devez ensuite faire est, pour émettre le 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; 
} 

ensuite ces informations enhenced (en cours) est passé à la fente à mon état où j'ai choisi d'appeler la transition correcte qui fait le travail. Vous pouvez lier plus de transitions, si vous en avez besoin.

Mais le plus important, vous n'avez pas besoin de reprogrammer la transition, une pensée que je détestais vraiment.

Merci pour votre aide, je ne pouvais pas le faire seul.

+0

Cette solution est correcte, mais l'état personnalisé est inutile. Un 'QSignalTransition' peut être utilisé pour connecter votre bouton à la machine. Vous pouvez intercepter 'QStateMachine :: SignalEvent' dans' eventTest' d'une transition personnalisée. Le 'SignalEvent :: arguments' vous donne accès aux arguments du signal, au cas où vous auriez besoin de les tester. Vous pouvez également tester d'autres conditions ici. –

0

Peut-être que vous devriez jeter un oeil aux signaux/mécanisme de fente. Je pense que c'est ce dont vous avez besoin pour réaliser ce que vous voulez. Rendez votre onTransition fonction un emplacement à la place d'un gestionnaire d'événements et connectez-le au signal clicked du bouton

classe validateBoatTransition: QtEventTransition publique {...

public slots: 
    void onTransition(); 

... 

}

Quelque part dans votre code, connectez-vous sur le bouton à l'emplacement:

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

Chaque fois que le bouton sera cliqué l'exécution passera par la fonction onTransition.

+0

C'est ce que j'avais. Mais ça a été compliqué. Je n'ai pas de bouton. Ceci est une partie de mon programme. – Thomas

0

Je pense que vous essayez d'utiliser de mauvaises classes/mécanismes pour atteindre vos objectifs. Si je vous comprends bien, vous avez une interface graphique et après avoir cliqué sur un bouton, vous voulez valider certaines choses et si cette validation est réussie, la machine d'état devrait changer son état. Je vous écris cette façon:

Créer une classe pour gérer la 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   
}; 

Ensuite, vous connectez votre QPushButton :: clicked() à BoatValidator :: validate() et utiliser BoatValidator :: boatTransition () signal pour conduire la machine d'état:

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); 

en général, je aurait le signal utiliser pour conduire la machine d'état, à moins que certaines transitions sont événement évidemment entraîné (par exemple, certains QEvent :: Entrez/QEvent :: Laisser sur les widgets GUI, etc.).

+0

Merci, votre idée a bien fonctionné. Mais maintenant, le code semble aussi désordonné qu'avant. Et si la transition ne change pas l'état cela ressemble à un gaspillage de code – Thomas

+0

Oui, le code utilisant QStateMachine peut parfois être désordonné et je n'ai pas de solution testée qui le rendrait plus clair. Je ne comprends pas votre commentaire sur le "gaspillage de code" dans la "transition" - de quoi parlez-vous? – chalup