[Qt入门篇]14 Qt状态机框架——进入和退出状态
(2016-04-20 21:05:26)
标签:
qstateassignproperqstateexited()qstateentered() |
分类: Qt入门到进阶 |
作者:taohe_qt 时间:2016/4/20
原创文章,可以转载,转载时请以超链接形式保留本文地址、作者信息和本声明。否则将追究法律责任。
在上一节中,我们实现了具有三个状态的状态机,但是这个状态机仅仅是声明了三个状态,定义了状态迁移,没有就进一步完成其他动作。如何在改变状态时做一些操作呢?
1 设置属性值
假设有这样一种场景,在进入某一个状态时在按钮标签上显示处当前状态标识。对于这样的功能,我们可以通过这个接口来实现:
void QState::assignProperty(QObject *object, const char *name, const QVariant &value)
QState::assignProperty分配指定属性值之后,当进入该状态时,状态机会设置该状态的属性为设定值,说起来比较拗口,还是看代码比较明确:
声明:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
public:
private:
};
#endif // MAINWINDOW_H
实现:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QState *s1 = new QState();
QState *s2 = new QState();
QState *s3 = new QState();
machine.addState(s1);
machine.addState(s2);
machine.addState(s3);
s1->addTransition(ui->button, SIGNAL(clicked()), s2);
s2->addTransition(ui->button, SIGNAL(clicked()), s3);
s3->addTransition(ui->button, SIGNAL(clicked()), s1);
// 分配属性
s1->assignProperty(ui->button, "text", "S1");
s2->assignProperty(ui->button, "text", "S2");
s3->assignProperty(ui->button, "text", "S3");
machine.setInitialState(s1);
machine.start();
}
MainWindow::~MainWindow()
{
delete ui;
}
运行之后,点击按钮,按钮标签会发生变化。
属性不仅仅有text,还有大小、颜色、位置等等,所有的属性都是可以定义的。具体内容参考《[Qt入门篇]5
Qt的属性系统——声明属性》。
2 关联信号槽
Qt状态机有这样一个特性:进入某个状态时会触发QState::entered()信号,离开状态时触发QState::exited()信号,如此,我们使用槽函数关联这两个信号就可以做一些额外的操作了。还是之前的代码,增加两个槽函数,输出字符串:
声明如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
public:
public slots:
private:
};
#endif // MAINWINDOW_H
实现:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QState *s1 = new QState();
QState *s2 = new QState();
QState *s3 = new QState();
machine.addState(s1);
machine.addState(s2);
machine.addState(s3);
s1->addTransition(ui->button, SIGNAL(clicked()), s2);
s2->addTransition(ui->button, SIGNAL(clicked()), s3);
s3->addTransition(ui->button, SIGNAL(clicked()), s1);
// 分配属性
s1->assignProperty(ui->button, "text", "S1");
s2->assignProperty(ui->button, "text", "S2");
s3->assignProperty(ui->button, "text", "S3");
connect(s1, SIGNAL(exited()), this, SLOT(OnExitStateS1()));
connect(s2, SIGNAL(entered()), this, SLOT(OnEnterStateS2()));
machine.setInitialState(s1);
machine.start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::OnExitStateS1(void)
{
qDebug() << "Exit s1";
}
void MainWindow::OnEnterStateS2(void)
{
qDebug() << "Enter s2";
}
运行之后,在离开S1进入S2的状态迁移中会输出两个字符串。
3 重载onEntry和onExit
如果我们要自定义一个状态的话,除了设置属性和信号槽之外,我们还可以通过重载接口实现进入和退出时执行一些操作。
一般我们自定义状态类继承QState,QState继承自QAbstractState,QabstractState有两个纯虚函数(接口):
virtual void onEntry(QEvent *event) = 0
virtual void onExit(QEvent *event) = 0
我们重载上述两个接口就可以该状态进入和退出时做操作了,看下面的代码:
声明:
#ifndef CMYSTATE_H
#define CMYSTATE_H
#include
class CMyState : public QState
{
public:
protected:
};
#endif // CMYSTATE_H
实现:
#include "mystate.h"
#include
CMyState::CMyState()
{
}
void CMyState::onEntry(QEvent *event)
{
qDebug() << "Enter CMyState";
}
void CMyState::onExit(QEvent *event)
{
qDebug() << "Exit CMyState";
}