The next version of Qt adds a framework for defining and executing hierarchical finite state machines in Qt applications. With Qt State Machines you can effectively model how components react to events over time; these state machines are a natural extension to Qt's event-driven programming model. State machines allow you to express the behavior of your application in a more rigid, explicit way, resulting in code that's easier to test, maintain and extend. This session presents the core concepts and functionality of Qt State Machines.
Presentation by Kent Hansen held during Qt Developer Days 2009.
http://qt.nokia.com/developer/learning/elearning
2. About Me (Kent Hansen)
• Working on Qt since 2005
• QtScript
• Qt State Machine framework
• Plays harmonica and Irish whistle
2
3. Goals For This Talk
• Introduce the Qt State Machine Framework (SMF)
• Show how to incorporate it in your Qt application
• Inspire you to think about how you would use it
3
4. Agenda
• State machines – what and why?
• Statecharts tour
• Qt State Machine tour
• Wrap-up
4
5. Qt State Machine Framework (SMF)
• Introduced in Qt 4.6
• Part of QtCore module (ubiquitous)
• Originated from Qt-SCXML research project
5
6. Qt State Machine Framework (SMF)
• Provides C++ API for creating hierarchical finite
state machines (HFSMs)
• Provides “interpreter” for executing HFSMs
6
7. State Chart XML (SCXML)
• “A general-purpose event-based state machine
language”
• W3C draft (http://www.w3.org/TR/scxml/)
–Defines tags and attributes
–Defines algorithm for interpretation
7
8. Statecharts – Some use cases
• State-based (“fluid”) UIs
• Asynchronous communication
• AI
• Gesture recognition
• Controller of Model-View-Controller
• Your new, fancy product (e.g. “Hot dog oven”)
8
11. Why State Machines in Qt? (II)
• Program = Structure + Behavior
• C++: Structure is language construct
• C++: Event-driven behavior is not language
construct
11
12. Why State Machines in Qt? (III)
• Qt already has event-based infrastructure
• Event representation (QEvent)
• Event dispatch
• Event handlers
• So what's the problem?
12
14. The spaghetti code incident (I)
“On button clicked:
if X, do this
else, do that”
14
15. The spaghetti code incident (II)
“On button clicked:
if X, do this
else, if Y or Z
if I and not J do that
else, do that other thing
else, go and have a nap”
15
16. ifs can get iffy; whiles can get wiley
• if-statements --> state is implicit
• Control flow and useful work jumbled together
• Hard to understand and maintain
• Hard to extend
16
21. What's in it for YOU?
• Write more robust code
• Have your design and implementation speak the
same language
• Cope with incremental complexity
21
22. Qt + State Machines = Very Good Fit
• Natural extension to Qt's application model
• Integration with meta-object system
• Nested states fit nicely with Qt ownership model
22
24. When NOT to use Qt SMF?
• Lexical analysis, parsing, image decoding
• When performance is critical
• When abstraction level becomes too low
• Not everything should be implemented as a (Qt)
state machine!
24
25. Agenda
• State machines – what and why?
• Statecharts overview
• Qt State Machine tour
• Wrap-up
25
33. Behavioral Inheritance
• States implicitly “inherit” the transitions of their
ancestor state(s)
• Enables grouping and specialization
• Analogue: Class-based inheritance
33
40. Agenda
• State machines – what and why?
• Statecharts overview
• Qt State Machine tour
• Wrap-up
40
41. Qt State Machine tour
• API introduction w/ small example
• Events and transitions
• Working with states
• Using state machines in your application
41
42. Qt State Machine API
• Classes for representing states
• Classes for representing transitions
• Classes for state machine-specific events
• QStateMachine class (container & interpreter)
42
45. State machine set-up recipe
• Create QStateMachine
• Create states
• Create transitions between states
• Hook up to state signals (entered(), finished())
• Set the initial state
• Start the machine
45
46. State machine event processing
• State machine runs its own event loop
• QEvent-based
• Use QStateMachine::postEvent() to post an event
46
47. Transitions (I)
• Abstract base class: QAbstractTransition
–bool eventTest(QEvent*);
• Has zero or more target states
• Add to source state using QState::addTransition()
47
48. Transitions (II)
• Convenience for Qt signal transitions:
addTransition(object, signal, targetState)
• Standard Qt event (e.g. QMouseEvent) transitions
also supported
– QEventTransition
48
49. Responding to state changes
• QAbstractState::entered() signal
• QAbstractState::exited() signal
• QAbstractTransition::triggered() signal
• QState::finished() signal
49
50. Composite states
• Follows Qt object hierarchy
• Pass parent state to state constructor
QState *s1 = new QState();
QState *s11 = new QState(s1);
QState *s12 = new QState(s1);
QFinalState *s13 = new QFinalState(s1);
50
51. Paralell state group
• Set the state's childMode property
QState *s1 = new QState();
s1->setChildMode(QState::ParallelStates);
QState *s11 = new QState(s1);
QState *s12 = new QState(s1);
51
52. History states
• QHistoryState class
• Create as child of composite state
• Use the history state as target of a transition
QState *s1 = new QState();
QHistoryState *s1h = new QHistoryState(s1);
…
s2->addTransition(foo, SIGNAL(bar()), s1h);
52
54. Scenario: Game (I)
• Many different types of game objects
• Each type's behavior modeled as composite state
• Events trigger transitions
– Input (e.g. key press)
• States operate on the game object
–Setting properties (e.g. velocity)
–Calling slots
54
55. Scenario: Game (II)
• Each game object has its own state machine
• The machines run independently
• Separate, top-level state machine that
“orchestrates”
–Game menus & modes
–Start/quit
55
56. Scenario: Game (III)
• Presence of a state machine is encapsulated
• Up to each type of object
• “Simple” objects don't need to use a state machine
56
57. States and animations
• Integrates with Qt animation framework (also new
in Qt 4.6)
• QAbstractTransition::addAnimation()
• Almost all Qt animation examples use Qt SMF
57
58. My tips (I)
• Use the meta-object system integration
–assignProperty(object, propertyName, value)
–entered() and exited() signals
58
59. My tips (II)
• Use composition
–Build complex behavior from simple states
–Take advantage of behavioral inheritance!
–Don't subclass unnecessarily
59
60. My tips (III)
• Always draw the statechart first
–Visualizing the design from C++ is hard
–The statechart is the design document
60
61. Agenda
• State machines – what and why?
• Statecharts tour
• Qt State Machine tour
• Wrap-up
61
62. Summary (I)
• Statecharts are a powerful tool for modeling
complex, event-driven systems
–General-purpose
–Well-defined semantics
62
63. Summary (II)
• With the Qt State Machine Framework, you can
build and run statecharts
• Write more robust code
• You need to consider when/where/how to use it
63
64. The Future (Research)
• Qt-SCXML to become part of Qt?
• Qt state machine compiler
• Visual design tool?
• Your feedback matters!
64