Probably the best way to implement FSMs in OOP languages is sticking to the State Design Pattern
That pattern provides a general structure to design and implement FSMs, dividing the FSM in two "sides": The context and the state, being the state a hierarchy of all the different states the context can have (a context can only have a very limited amount of states at a single time, usually only one). Then, the state transitions are modeled, usually either in the client (the class that uses the context will decide when to explicitly transition to a new state, making the context instance behave differently), or in the states (when each state is responsible of checking the transition conditions and perform the actual transition). The first approach has the advantage of a lower cohesion between states, making them reusable in implementations of other FSMs, but with a much more complex client class. The second approach has the opposite side effects.
In your case, I'd model System with the role of Context, State with the role of State, and Menu (and its submenus) as different ConcreteStates. If StepSequencer and SamplePad are to be exclusive of a single menu/submenu, they'd be attributes of that individual state. Otherwise, (i.e., shared or persistent between menus), as attributes of System. That decision will depend on your actual needs.
Now, about your design (and this is a little off-topic), StepSequencer and SamplePad don't look like actual states (neither by their uses nor by their names). Personally, I'd bet it's that way just because their interface is apparently identical to that of states (def buttonPress(self, numberButton):
). If that's the reason, and you did it that way to avoid duplicating code, don't. It's okay to have code duplicated in certain occasions (e.g., when the base interface is likely to change in different directions over time, as stated by Robert C. Martin in his book Clean Architecture). Keep this in mind and consider deriving them from a different base class other than State.
Best Answer
What you are experiencing is called 'Code Smell' and is a good indicator that you might be doing something wrong. Luckily though, you saw the problem and already came up with a great solution, so there's not much for me to say here. A state machine works perfectly for what you're doing here.
Drawing it out might also help to try and find other states you might not think of (Running, spin cycle, cool down, filling), as well as allowing you to define transition requirements between states (probably don't want to let the door open during the spin cycle, but maybe the filling state allows the door to be opened to add garments).
Obviously you can be as detailed or ambiguous as you want, do as much as fits your needs!