1

我正在尝试构建 QT 状态机。我有一些状态,对于那些状态,我需要转换来改变我的 gui 上的图形。我遇到的问题和我要问的唯一原因,我被卡住了,第 1 点。

编译器无法识别 QTEventTransition。我在 Windows 上使用 QT Creator 运行了 QT 4.6。编译器没有找到 Header #include <QtEventTransition>

这就是我所做的,我从来没有这样做过,但我认为它应该是正确的,我有一个头文件,其中我的转换声明如下:

       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
*/
}

我想要的是,如果通过按钮(单击)激活转换,它应该触发这个转换!

我搜索了网络,但找不到解决方案。我可以这样做吗?我应该想。

你的托马斯

4

3 回答 3

0

也许你应该看看信号/槽机制。我认为这是实现您想要的目标所需要的。

使您的onTransition函数成为插槽而不是事件处理程序,并将其连接到clicked按钮的信号。

类 validateBoatTransition : 公共 QtEventTransition { ...

public slots:
    void onTransition();

...

}

在代码中的某处,将按钮连接到插槽:

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

每次单击按钮时,都会通过 onTransition 函数执行。

于 2010-04-07T23:15:33.760 回答
0

我认为您正在尝试使用错误的类/机制来实现您的目标。如果我对你的理解正确,你有一些 GUI,点击一些按钮后你想验证一些东西,如果这个验证成功,状态机应该改变它的状态。我会这样写:

创建一些类来处理验证:

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

通常我会使用信号来驱动状态机,除非某些转换明显是事件驱动的(例如 GUI 小部件上的一些 QEvent::Enter/QEvent::Leave 等)。

于 2010-04-08T07:13:03.673 回答
0

我想做的是构建一个 Qt 状态机。问题是我无法触发我自己的转换(更不用说我自己的事件了)。给出的答案很好,但会导致代码混乱。如果我不能使用 QT 转换,我为什么要使用 QT 状态机?如果你创建一个新项目,上面的第一个问题就解决了。QT 创建者很烦人。但是现在我的解决方案在这里,可能对其他人有所帮助。

首先我的状态:

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

然后这个增强的信息(当前)被传递到我所在状态的槽,在那里我选择调用正确的转换来完成工作。如果需要,您可以将更多转换链接到它。

但最重要的是你不需要重新编程转换,我真的不喜欢这种想法。

谢谢你的帮助,我一个人做不了。

于 2010-04-12T11:30:04.850 回答