In another question you tell me to use QStateMachine.
I'm new to Qt and it's the first time i use the objects so I make a lot of logical mistake, so using QStateMachine it's a big problem...
It's the only way to do thath ? I try to explain my program:
I want to create a card's game and in the previous version I've used an old graphics library with this sequence of commands:
-> print cards on the scene
-> wait for a mouse input (with a do-while)
-> if(isMouseClick(WM_LBUTTONDOWN))
-> if(mouse position is on the first card)
-> select that card. So i wish to do the same thing with QGraphics.
In this way I tell the program:
-> print cards
-> wait for a mouse event
-> print the card that I've selected with that event.
Now I want to change the program graphics and I've introduced QGraphics. I've created a scene and print all the objects "card" on it so now i want to tell the program:
-> print the object and wait the mouse input
-> if a card is to selected with the left clik
-> print that card in scene, wait 1/2 second and go ahead with the program
The problem is that I use a for
1 to 20 (I must run that 20 times in a match).
I've tried to lauch the program with a random G1 and COM play but the application freeze until the last execution of the for
and I print on the scene only the last configuration of cards.
That is the reason because previously I said I want the program to stop...
It is possible to do without QStateMachine ? Simply telling him: "pause", print this situation, wait for mouse and go ahead ?
In qt you don't need to actively wait for an event (and usually shouldn't). Just subclass the event handling method of a widget which is part of the main interface.
For instance this is the code which use a subclass of a
QGraphicsItem
to change the game state. You could do the same with the scene itself, widgets, etc... but it should usually be like this.even if you are somehow using a state machine,
makeQuickChangesToGameState()
should just trigger the machine state change, and go back asap.The below is a complete example, 71 lines long, presented in the literate programming style. It is also available on github. The example consists of a qmake
.pro
file, not shown, andmain.cpp
, shown in the entirety below. The example has the following structure:Main
First, let's set up our scene:
The state machine has three states:
We'll use helper functions to declaratively add behaviors to the machine. This isn't the only possible pattern, but it works and is fairly easy to apply. First, when any items are selected, the state changes from
s_idle
tos_selected
:Then, after a timeout, the state changes to
s_ready
:If the items are deselected, we go back to
s_idle
:Since we don't have much better to do, we can simply deselect all items once the
s_ready
state has been entered. This makes it clear that the state was entered. Of course, it'll be immediately left since the selection is cleared, and we indicated above thats_idle
is the state to be when no items are selected.We can now start the machine and run our application:
Note the minimal use of explicit dynamic memory allocation, and no manual memory management whatsoever.
Card Item
The
CardItem
class is a simple card graphics item. The item is selectable. It could also be movable. The interaction is handled automatically by the graphics view framework: you don't have to deal with interpreting mouse presses/drags/releases manually - at least not yet.State Machine Behaviors
It is helpful to factor out the state machine behaviors into functions that can be used to declare the behaviors on a given state.
First, the delay - once the
src
state is entered, and a given number of millisconds elapses, the machine transitions to the destination state:To intercept the selection signals, we'll need a helper class that emits a generic signal:
We then leverage such universal signal source to describe the behavior of transitioning to the destination state when the given scene has a selection iff
selected
is true, or has no selection iffselected
is false:Header and Footer
The example begins with the following header:
It ends with the following footer, consisting of moc-generated implementations of the signals and object metadata for the
SignalSource
class.