Results 1 to 2 of 2

Thread: Changing my QML thought my QStateMachine

  1. #1
    Join Date
    Jun 2015
    Posts
    1
    Qt products
    Qt5

    Default Changing my QML thought my QStateMachine

    Hello,

    I want to use QML with a QStateMachine. My StateMachine can be quite complex and I want to be able to test it. I want as little logic as possible in my QML.

    I am not sure if I'm on the right way, but here is what I was thinking:
    - Use a QML Main with a Loader.
    - Create my QStateMachine
    - On state change, load the desired page through the loader.

    I have trouble with the last one. How can I tell my Qml which part to load? For example, let's say I have this :

    Qt Code:
    1. Item {
    2. id : mainWindow
    3. visible: true
    4. width: 1920
    5. height: 1080
    6.  
    7. Loader { id: pageLoader
    8. objectName: "pageLoader"
    9. anchors.fill:parent
    10. source: "splashScreen/SplashScreen.qml"
    11. }
    12. }
    To copy to clipboard, switch view to plain text mode 

    Then, from my C++ code, when my StateMachine tells me to change screen, I do:

    Qt Code:
    1. QObject* QmlStartupViewBuilder::createNextScreen()
    2. {
    3. QObject* root = m_engine->rootObjects()[0];
    4. QQuickItem* loaderItem = root->findChild<QQuickItem*>("pageLoader");
    5. loaderItem->setProperty("source", QUrl(QStringLiteral("qrc:/screens/screen2/Screen2.qml")));
    6. }
    To copy to clipboard, switch view to plain text mode 

    It works, but I am not sure it is the best solution. I guess I should use a slot/signal from my ViewBuilder to call my qml. But how?

    Thanks a lot.
    Last edited by jfdesjardins2; 18th December 2016 at 23:32.

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Changing my QML thought my QStateMachine

    The general approach is good, but instead of "directing" the QML side you provide data the QML side can react to.

    Basically you combine two things:
    * QML can easily and automatically react to changes in property values. This is a central concept in QML, called "property bindings"
    * QStateMachine can assign values to properties when it enters state, see QState::assignProperty().

    You combine that by having a mediator object, something that is known to both the state machine and the QML engine, carrying the properties that you want the state machine to control and the QML side to follow.

    Qt Code:
    1. class AppState : public QObject
    2. {
    3. Q_OBJECT
    4.  
    5. // make this a QUrl type property if you need to pass the full URL
    6. // here I assume that you pass a path relative to the QML that has the Loader
    7. Q_PROPERTY(QString currentScreen MEMBER m_currentScreen NOTIFY currentScreenChanged)
    8.  
    9. public:
    10. explicit AppState(QObject *parent = 0);
    11.  
    12. signals:
    13. void currentScreenChanged();
    14.  
    15. private:
    16. QString m_currentScreen;
    17. };
    To copy to clipboard, switch view to plain text mode 
    An instance of that is passed to both QML engine setup and state machine setup
    Qt Code:
    1. AppState *appState = new AppState();
    2.  
    3. qmlEngine->rootContext()->setContextProperty("_appState", appState);
    4. createStateMachine(appState);
    To copy to clipboard, switch view to plain text mode 

    The State machine can then do things like this
    Qt Code:
    1. QState *startState = new QState(m_stateMachine);
    2. startState->assignProperty(m_appState, "currentScreen", "screens/screen2/Screen2.qml");
    To copy to clipboard, switch view to plain text mode 

    The QML side can then do things like
    Qt Code:
    1. Loader {
    2. source: _appState.currentScreen
    3. }
    To copy to clipboard, switch view to plain text mode 

    A very similar technique can be done for the other way aroound, when the QML side needs to trigger state transitions.
    You either use an additional interface object or extend the AppState class.

    Qt Code:
    1. public slots:
    2. void reset() { emit triggerReset(); }
    3.  
    4. signals:
    5. void triggerReset();
    To copy to clipboard, switch view to plain text mode 

    The state machine can use that as a source for transitions
    Qt Code:
    1. runningState->addTranstion(m_appState, SIGNAL(triggerReset()), startState);
    To copy to clipboard, switch view to plain text mode 

    The QML side can ask for that
    Qt Code:
    1. MouseArea {
    2. onClicked: _appState.reset();
    3. }
    4. // or
    5. Keys.onEscapePressed: _appState.reset()
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _

Similar Threads

  1. Replies: 0
    Last Post: 30th March 2011, 10:02
  2. Replies: 4
    Last Post: 26th December 2009, 07:54
  3. QStateMachine
    By piotr.dobrogost in forum Qt Programming
    Replies: 3
    Last Post: 6th December 2009, 08:17
  4. make a widget paint itself even thought it is not shown
    By momesana in forum Qt Programming
    Replies: 7
    Last Post: 28th April 2008, 11:57
  5. Create Thought Balloons
    By Angelo Moriconi in forum Qt Programming
    Replies: 4
    Last Post: 11th January 2008, 09:15

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.