# Finite state machine menu design

This topic is 965 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I post here because the same concepts can be applied to a game:

I'm creating a FSM in python (it's a step sequencer and sample pad based on a Raspberry Pi 2).

Right now there are two states and the third is the Menu. This is handled by a class System which handles all the states. The Menu state has to edit the attributes of the other states, so I passed the other states to its constructor.

class State(object):
def buttonPress(self, numberButton):
raise NotImplementedError

class StepSequencer(State):
def buttonPress(self, numberButton):
...

def buttonPress(self, numberButton):
...

self.stepsequencer = stepSequencer
def buttonPress(self, numberButton):
...

def __init__(self, text):
self.text = text

class System(object):
def __init__(self):
self.stepsequencer = StepSequencer()
def setState(self,state):
self.state = state
def buttonPress(self, numberButton):
self.state.buttonPress(numberButton)

I can't figure out how to create the structure for the menu. I thought of creating a class MenuItem for every menu item so the Menu state has all these objects and can change the current MenuItem, however there are some things that I cannot overcome:

• how can I declare all the menu items and pass them to the Menu state to create dynamically the structure of the menu?

Step Sequencer settings:
Set samples
Set volume
Set samples
Set volume

for example if I want to have a slider that sets the volume, do I have to create another state to handle this? This state can be another state of the System or it must be a substate of the Menu state?

• can I execute the code of each state using this logic? :

while(system.state = system.stepsequencer):
...
...

The state is changed by a listener in another thread. This seems a very unorthodox way of handling states but it seems to work. If this is effective, how can I handle the Menu substates?

##### Share on other sites

I have a really hard time understanding what you're doing. Deriving a menu from State is particularly confusing to me. The best I can think of is that you have a program where you only show one sub-menu, so each sub-menu becomes a state, and you jump between them to switch sub-menus?

If so, you are basically duplicating menu structure onto the state structure, which explains why you are having difficulties in having a dynamic menu structure (since that would imply a dynamic state structure, which is counter-intuitive in most forms of state machines).

In addition, your code looks very heavy class oriented, with classes for almost everything. While this is normal in languages like Java or C#(?), it's not very "python". Python tends to be much more lightweight.

Since I am just speculating here, I cannot really give you an answer to the questions. Instead I'll just open a discussion.

One thing that may be helpful, is to let go of the idea that a menu is a state. A menu is a data structure with sub-menus and items, and perhaps some callback functions, but it's not a state. How you display a menu in your program has nothing to do with the content of the menu.

You will likely have one or more program states that display a menu, and those states probably point into the menu data structure, but that makes the menu a data member of the state rather than being a state. (In other words, composition rather than inheritance.)

Finally, an alternative way to write a menu structure. Have a look at it, maybe you can use some parts of it.

class MenuItem:
def __init__(self, text, cb_func, param):
self.text = text
self.cb_func = cb_func
self.param = param

def click(self):
""" User clicked the item, call the function. """
self.cb_func(self.param)

def __init__(self, text, items):
self.text = text
self.items = items

def sequencer_steps(val):
# Handle sequencer steps click

def sequencer_volume(val):
# Handle sequencer volume click

seq_items = [MenuItem("seq steps up",    sequencer_steps,   1),
]

main_menu = Menu("main", main_items)

##### Share on other sites

Thank you for your answer. The project is structured so it has exactly 1 menu, so I thought that implementing it as a state should have sense. In fact if it isn't a state, how can the system know if the menu is active or not?

I must use this heavy class oriented approach, I know it's not a python strong point, however python is the best language for dealing with a Rasp Pi.

##### Share on other sites

Hmm, how to explain the difference between displaying a menu and the menu itself....

Right, let's say a book. It's a collection of pages with text, and if you're lucky, pictures as well.

There is also reading, the activity, where you read the content of the book.

Now, are you a book when you are reading?

Inheritance means "is a". If you inherit a menu from a state, a menu is a state.

I think a better way to express this is a state "reading", or a state "displaying the menu", and a separate data structure "book", or "menu".

##### Share on other sites

So I should have a state for displaying a menu, right?

##### Share on other sites

It may be a simple matter of renaming the state to "DisplayMenuState" or something.

Reviewing your questions under this assumption, I am afraid I didn't get much further.

how can I declare all the menu items and pass them to the Menu state to create dynamically the structure of the menu?

In standard Python you'd use a lightweight structure, and define the tree in data, as I have shown. You said you need the heavy class structure for some reason. I don't understand that, but if that's what you need, you need to find something list-like in your classes. Maybe a linked list?

for example if I want to have a slider that sets the volume, do I have to create another state to handle this? This state can be another state of the System or it must be a substate of the Menu state?

Both options would be feasible, I can't judge which solution is better under your class constraints.

can I execute the code of each state using this logic?

You already proved it was possible right? :)

The normal idea however is that you let the state itself execute its own code, ie  "current_state.run_tick()". I don't know if that is feasible for you.

1. 1
2. 2
3. 3
Rutin
18
4. 4
5. 5
JoeJ
12

• 14
• 9
• 22
• 9
• 31
• ### Forum Statistics

• Total Topics
632618
• Total Posts
3007485
• ### Who's Online (See full list)

There are no registered users currently online

×