加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[Qt入门篇]14 Qt状态机框架——进入和退出状态

(2016-04-20 21:05:26)
标签:

qstateassignproper

qstateexited()

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

{

    Q_OBJECT

 

public:

    explicit MainWindow(QWidget *parent = 0);

    ~MainWindow();

 

private:

    Ui::MainWindow *ui;

    QStateMachine machine;

};

#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

{

    Q_OBJECT

 

public:

    explicit MainWindow(QWidget *parent = 0);

    ~MainWindow();

 

public slots:

    void OnExitStateS1(void);

    void OnEnterStateS2(void);

 

private:

    Ui::MainWindow *ui;

    QStateMachine machine;

};

 

#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 重载onEntryonExit

如果我们要自定义一个状态的话,除了设置属性和信号槽之外,我们还可以通过重载接口实现进入和退出时执行一些操作。

一般我们自定义状态类继承QStateQState继承自QAbstractStateQabstractState有两个纯虚函数(接口):

virtual void onEntry(QEvent *event) = 0

virtual void onExit(QEvent *event) = 0

我们重载上述两个接口就可以该状态进入和退出时做操作了,看下面的代码:

声明:

#ifndef CMYSTATE_H

#define CMYSTATE_H

 

#include

 

class CMyState : public QState

{

public:

    CMyState();

 

protected:

    virtual void onEntry(QEvent *event);

    virtual void onExit(QEvent *event);

 

};

 

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

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有