Реализация QT EventTransition - PullRequest
       33

Реализация QT EventTransition

1 голос
/ 08 апреля 2010

Я пытаюсь построить QT State Maschine. У меня есть несколько штатов, и для этих штатов мне нужен переход, который меняет графику на моем графическом интерфейсе. Проблема, которая у меня есть, и единственная причина, по которой я спрашиваю, я застрял и точка 1.

Компилятор не может идентифицировать QTEventTransition. У меня QT 4.6 работает с QT Creator на Windows. Компилятор не находит заголовок #include

Это то, что я сделал, я никогда не делал этот bevor, но я думаю, что это должно быть правильно, у меня есть файл заголовка, в котором мои декларации объявлены так:

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

Чем у меня есть файл Cpp, где у меня есть это:

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


}


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

То, что я хочу, это то, что если переход активируется кнопкой (нажата), он должен запустить этот переход!

Я искал в сети, но не могу найти решение. Могу ли я сделать это? Я должен я думаю.

Ваш Томас

Ответы [ 3 ]

0 голосов
/ 08 апреля 2010

Я думаю, что вы пытаетесь использовать неправильные классы / механизмы для достижения ваших целей. Если я вас правильно понимаю, у вас есть некоторый графический интерфейс, и после нажатия какой-либо кнопки вы хотите проверить некоторые вещи, и если эта проверка прошла успешно, конечный автомат должен изменить свое состояние. Я бы написал так:

Создайте некоторый класс для обработки проверки:

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

Затем вы подключаете свой QPushButton :: clicked () к BoatValidator :: validate () и используете сигнал BoatValidator :: boatTransition () для управления конечным автоматом:

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

Обычно я использую сигнал для управления конечным автоматом, если только некоторые переходы не являются явно управляемыми событиями (например, некоторые QEvent :: Enter / QEvent :: Leave на графических элементах GUI и т. Д.).

0 голосов
/ 12 апреля 2010

Что я хотел сделать, так это собрать Qt State Machine. Проблема заключалась в том, что я не мог инициировать свои собственные переходы (не говоря уже о моих собственных событиях). Полученные ответы хорошие, но приведут к грязному коду. Зачем мне использовать конечный автомат QT, если я не могу использовать переходы QT? Первая проблема, описанная выше, решается, если вы создаете новый проект. QT Creater очень раздражает. Но вот теперь мое решение, может ли оно помочь другим.

Первый мой штат:

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

Нормально, но вы видите, что я добавил слот. Этот слот позволяет мне подключить к нему нижний сигнал или сигнал нажатия мыши виджета!
Как это:

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

Теперь все, что мне нужно, - это запустить объявленное Событие, подобное этому:

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

когда слот вызывался:

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

Конечный автомат QT теперь будет вызывать все переходы, связывая это состояние:

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

Что такого замечательного, что я осмелюсь опубликовать? Ну, во-первых, вы можете связать Qt SM с виджетом, где вызывается событие нажатия мыши или что-то еще, и обрабатывать необработанные данные до уровня, который вам понадобится позже в вашей программе. Все, что вам нужно сделать, это испустить сингал:

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

Затем эта расширенная информация (текущая) передается в слот в моем состоянии, где я решил вызвать правильный переход, который выполняет эту работу. Вы можете связать больше переходов с ним, если вам это нужно.

Но большинству важно, что вам не нужно перепрограммировать Переход, думаю, мне это очень не понравилось.

Спасибо за вашу помощь, я не мог сделать это один.

0 голосов
/ 08 апреля 2010

Может быть, вам стоит взглянуть на механизм сигналов / слотов. Я думаю, что это то, что вам нужно для достижения того, что вы хотите.

Сделайте вашу onTransition функцию слот вместо обработчика событий и подключите его к сигналу clicked кнопки.

класс validateBoatTransition: public QtEventTransition { ...

public slots:
    void onTransition();

...

}

Где-то в вашем коде подключите кнопку к слоту:

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

Каждый раз, когда нажимается кнопка, выполнение будет проходить через функцию onTransition.

...