[Qt-interest] How to change QState when clicking a QListView

K. Frank kfrank29.c at gmail.com
Fri Aug 6 19:11:08 CEST 2010


Hello François -

See response, below.

2010/8/6 Mandeep Sandhu <mandeepsandhu.chd at gmail.com>:
> Since you are only passing the QModelindex around, I assume you'll
> have access to the model in your 'playerState'.
> ...
>> But I'd need both (retrieve the clicked item + go to the targeted state).
>> ...
>> François

> Thanks a lot your answer !
> Just to be sure I've understand, I should basically :

I'm not that familiar with the specifics of Qt's state-machine framework,
but I can give you my thoughts on how it might work.

> - Build a custom QEvent, let's say "ItemClickEvent", with a "data"
> property,

Yes, and the "data" property would tell you which item in your
list had been clicked.

> - Set my QListView to accept "ItemClickedEvent",

This I don't follow.  I don't see why you would be sending this
(or any other event) to your QListView.

> - Connect the QAbstractView::clicked ( const QModelIndex &index ) signal
> to a custom slot (which I already do),

Yes, you would have some slot which translates the signal to
an event.  (But you may be able to avoid this step: see below.)
The slot then instantiates an ItemClickedEvent, sets its "data"
property to index (the signal's argument), and posts the event
to your state machine.

> - Add a transition from my source state to my targeted state when the
> ItemClickedEvent occurs (using a QEventTransition),

Yes, your "listState" would have a transition triggered by the
IntemClickedEvent that takes it to your "playerState."

> - In my custom slot, instantiate my ItemClickedEvent class, set its "data"
> property to whatever I need,

Yes, and presumably what you need is to set "data" to index, the
argument of the clicked signal.

> and send the Event via
> QCoreApplication::notify(),

I could be wrong, but since your dealing with a state machine, it's
probably more appropriate to use QStateMachine.postEvent().
In somewhat compressed form:

   stateMachine.postEvent (new ItemClickedEvent (index));

(For all I know, postEvent and notify may be equivalent, in that
postEvent may resolve to notify under the hood.)

> - And finally, use the event handed to my target state onEntry() method.

Yes (presumably your target state is your 'playerState'), and in
particular, query the event for the index of the item clicked.

> (I tried something quite similar, but, instead of sending a QEvent, I
> tried to send a custom signal -and it didn't work-.)

Following up on my earlier comment, it looks like Qt's state-machine
framework does support using signals instead of events (which it
then wraps as events for you).

If I understand this correctly, you could forgo defining a custom
event (the ItemClickedEvent), and having your slot instantiate and
post this event.

QState has a version of addTransition that takes signals:

   QSignalTransition *addTransition (QObject *sender, const char
*signal, QAbstractState *target)

So, as I understand it, you could do something like this:

   listState->addTransition (listView, SIGNAL (clicked (const
QModelIndex &index)), playerState);

Then when the signal fires, your state machine gets a
QStateMachine::SignalEvent that ultimately gets passed
to playerState->onEntry(), and the index argument of the
clicked signal appears to be exposed through
QStateMachine::SignalEvent.arguments().

So it looks like in terms of mapping the signal to an event,
instantiating the event, and then posting it, Qt will do all
that work for you, so you can save a few lines of typing,
and not have to write your own custom slot and event.

> Thanks again for your help, I really appreciate it !
>
> François

Good luck.


K. Frank




More information about the Qt-interest-old mailing list