zoukankan      html  css  js  c++  java
  • Qt 状态机框架学习(没学会)

    Qt状态机框架是基于状态图XML(SCXML) 实现的。从Qt4.6开始,它已经是QtCore模块的一部分。尽管它本身是蛮复杂的一套东西,但经过和Qt的事件系统(event system)、信号槽(signals and slots)及属性系统(property system)深度整合,它使用门槛并不高。

    一些概念

    Qt的手册中The State Machine Framework一文对Qt状态机框架及使用进行了介绍,可是还是发现看看基本的概念(详见  SCXML   的  第三部分 )更有帮助一点。

    基本概念

    最基本的概念是:

    • 状态(state)
    • 转换?过渡?(transition)
    • 事件(events)

    每一个state包含一个transition的集合,这些transition定义了如何对events进行响应。events可以由状态机本身或外部实体产生。

    在一个经典状态机中,状态机总是处于一个单一的state中。这个状态被称为active state。当event发生时,状态机将检查active state的包含的所有transition。如果它发现有一个和该event匹配,状态机将从当前的active state移动到该transition指定的state(称之为transtion的目标)。这样一来,目标state将成为新的active state。

    在transition的过程中,状态机可以执行一些动作(action)。每一个状态都可以包含onentry 和 onexit动作,transition本身也可以包含动作。当状态机通过一个名为T的transition从状态S1转换到S2,它先执行S1的 onexit 的动作,然后执行T本身包含的动作,最后执行S2 onentry的动作。

    Compound States

    一个state还可以嵌套其他的state。这样的state称为compound states(复合状态),我们称其为parent state,而被嵌套的则称为child state。子state又可以嵌套其他的state,直到任意深度。不包含任何子state的state,称为atomic state(原子状态)。

    当一个child state处于 acitve时,它的parent active 也必须处于active状态。这样一来,在任何一点我们都将拥有一个包含原子state和它所有祖先的active state的集合。(在后面我们将看到多个原子state可以同时处于active状态)。

    由于复合state的存在,transition将不再是从一个原子state到另一个原子state的转换,而是从一个active state集合到另一个集合的转换。如果transition的目标是一个原子state,那么状态机将不仅进入到该原子state,而且还将进入到它所有的为处于active的祖先state中。与此对应的是,transition的目标是一个组合state。在这种情况下,复合state的子state必须也被激活,由于transition并没有指定哪一个,这是需要active该复合state的initial state(初始状态)。如果该state依然是复合状态,将递归下去,直到原子 state。

    一个复合state还可以包含final 和 history state作为其child state。

    复合状态还会影响到transition的选择。当事件发生时,状态机从最深层嵌套的state(原子state)开始查找,如果未找到匹配的transition,则查找其parent state的transition,依次递归。如果状态机中所有transition均不匹配,事件被丢弃。

    Parallel States

    注:在SCXML中 Parallel States使用的是paralled 标签,前面提到的复合state和原子state都是用的state 标签。在Qt中,Paralled State和普通 state 是靠构造函数一个的参数进行区分的。

    Parallel States(平行状态) 与前面介绍的复合 state 有很大的不同:当一个复合state处于active时,有且只有一个child state处于acitve;而parallel state处于active时,所有的child state都必须处于active状态。

    当状态机进入平行state时,它也进入各个child state。各个child state可以采取不同的transition对event进行响应。

    Executable Content

    SCXML通过Executable Content(可执行内容?)提供了对数据(data model)进行修改和与外界实体进行交互的功能。

    回到 Qt

    这部分内容Qt Manual中给的太详细了,以至于都不知道该怎么向下写了。

    基本概念

    3个基本概念对照:

    state

    QAbstractState及其派生类

    transition

    QAbstractTransition及其派生类

    event

    Qt的信号和事件

    data

    Qt属性

    注意:QStateMachine本身是QState的派生类。这使得状态机可以嵌套,见qstatemachines-a-state-too 。

    • QObject
      • QAbstractState
        • QState
          • QStateMachine
        • QFinialState
        • QHistoryState
      • QAbstractTransition
        • QSignalTransition
        • QEventTransition
          • QKeyEventTransition
          • QMouseEventTransition
    • QEvent
      • QStateMachine::SignalEvent

      • QStateMachine::WrappedEvent

    transition的触发

    Qt的信号和事件都可以触发transition。那么是如何实现的呢?

    打开QAbstractTransition的Manual,可以看到两个protected的函数:

    virtual bool    eventTest ( QEvent * event ) = 0
    virtual void    onTransition ( QEvent * event ) = 0

    前者用来判断事件是否匹配,后者用来执行一些动作。

    两个具体类和对应的QEvent的派生类关系如下:

    QSignalTransition

    QStateMachine::SignalEvent

    QEventTransition

    QStateMachine::WrappedEvent

    进入状态后,状态机将active state的对应的transition进行注册:

    • 对于signal类型的,将该信号连接到一个私有槽函数,槽函数中生成一个内部的QStateMachine::SignalEvent事件

    • 对于event类型的,将直接在事件的对象安装事件过滤器,将事件拷贝并封装到一个内部的QStateMachine::WrappedEvent事件中。

    对于自定义事件,可以使用QStateMachine::postEvent()进行派发。

    参考

    http://blog.csdn.net/dbzhang800/article/details/6408008

  • 相关阅读:
    A1023 Have Fun with Numbers (20分)(大整数四则运算)
    A1096 Consecutive Factors (20分)(质数分解)
    A1078 Hashing (25分)(哈希表、平方探测法)
    A1015 Reversible Primes (20分)(素数判断,进制转换)
    A1081 Rational Sum (20分)
    A1088 Rational Arithmetic (20分)
    A1049 Counting Ones (30分)
    A1008 Elevator (20分)
    A1059 Prime Factors (25分)
    A1155 Heap Paths (30分)
  • 原文地址:https://www.cnblogs.com/findumars/p/5175966.html
Copyright © 2011-2022 走看看