Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Qt Academy Launch in California!

    Change QML-property in C++

    QML and Qt Quick
    5
    9
    11170
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Hedge last edited by

      I've got a ToolButton (QML Desktop Widgets) and want to change its icon.

      @ ToolButton{
      objectName: "imgConnected"
      iconSource: "images/not-connected.png"
      anchors.verticalCenter: parent.verticalCenter
      }@

      Now when I try to change the iconSource I do this:

      @
      QDeclarativeView view(QUrl("qml/MyProject/main.qml"));
      view.show();

      // get root object
      QObject *rootObject = dynamic_cast<QObject *>(view.rootObject());
      // find element by name
      QObject *image = rootObject->findChild<QObject *>(QString("imgConnected"));
      
      image->setProperty("iconSource", QString("D:/Dropbox/Projekte/MyProject/release/images/connected.png"));
      

      @

      (I know that I have to remove the absolute path, its just there for testing).

      My problem is that whenever this code is executed another window looking like the Mainwindow pops up for a second and then hides. The iconSource never changes visibly though.

      1 Reply Last reply Reply Quote 0
      • M
        mburakalkan last edited by

        What you can do is assign a variable for that icon and change that variable from C++ side so
        that icon updates.. I was using that technique for states and it was working well..

        1 Reply Last reply Reply Quote 0
        • H
          Hedge last edited by

          Can you provide an example?

          1 Reply Last reply Reply Quote 0
          • M
            mburakalkan last edited by

            Say you have a onStateChange slot somewhere in you QDV implementation and you want to change state property of you QML ui. You could write the slot like that

            @
            void SignageView::onStateChange(const QString &newState)
            {
            QDeclarativeProperty state(rootObject(), QString("state"));

            if (state.type() == QDeclarativeProperty::Invalid) {
                WRT("state propery is invalid, unable to change qml state..");
                return;
            } else {
                state.write(newState); // should reflect immediately
            }
            

            }
            @

            AFAIK as long as you provide the notify() calls of your QProperty's you can use those properties in QML too.

            1 Reply Last reply Reply Quote 0
            • M
              mario last edited by

              I think that you should try to solve this by having the C++ side "announcing" when is has changed to connected state.

              One way could be to set a context property:
              @
              view->rootContext()->setContextProperty("connected", mgr->isConnected());
              @
              You have to set this property each time the connection changes.

              The QML file could look something like this:

              @
              ToolButton {
              ...
              iconSource: connected ? "images/connected.png" : "images/disconnected.png"
              }
              @

              By doing this, the view controls what image should be shown when, not the C++ side.

              1 Reply Last reply Reply Quote 0
              • A
                andre last edited by

                First of all: I think your (Hedge) approach should work. If it does not, then that is worth digging in to further.

                On the other hand, I think that this approach is not the most elegant, and if possible, should be avoided. Instead, you can insert a QObject in your QML environment and use the property binding methods. For that to work, you need to create a QObject class like this:

                @
                class QmlCppMediator: public QObject {
                Q_OBJECT

                Q_PROPERTY (bool connected READ isConnected WRITE setConnected NOTIFY connectedChanged);

                public:
                QmlCppMediator(QObject* parent) :
                QObject(parent),
                m_connected(false) {}

                void setConnected(bool value) {m_connected = value; emit connectedChanged();}
                bool isConnected() {return m_connected;}
                

                signals:
                connectedChanged();

                private:
                bool m_connected;
                }@

                Of course, your bridge could have many more methods to interface between your QML and your C++ parts, and the properties could also be implemented in other ways. The idea is that you provide a "mediator":http://en.wikipedia.org/wiki/Mediator_pattern between your C++ and your QML.

                You can insert an instance (probably the instance) of this class using the setContextProperty method mentioned by mario above:

                @
                view->rootContext()->setContextProperty("cppInterface", m_qmlCppMediator);
                @

                You can then connect to the exposed properties like this:
                @
                ToolButton {
                ...
                iconSource: cppInterface.connected ? "images/connected.png" : "images/disconnected.png"
                }
                @
                You can of course group functionality that logically belongs together in such a mediator object, and use more than one of these.

                1 Reply Last reply Reply Quote 0
                • H
                  Hedge last edited by

                  Thanks for all your help. I implemented it as Andre said.

                  It finally works.

                  One error keeps bugging me though.
                  I've got bq. file:///D:/MyProject/main.qml:28: ReferenceError: Can't find variable: cppInterface
                  For some reasons it still works.

                  That is how my main-function looks like:

                  @int main(int argc, char *argv[])
                  {
                  QApplication app(argc, argv);

                  QmlApplicationViewer viewer;
                  viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
                  viewer.setMainQmlFile&#40;QLatin1String("main.qml"&#41;&#41;;
                  viewer.showExpanded();
                  
                  
                  QmlCppMediator m_qmlCppMediator;
                  QDeclarativeContext *context = viewer.rootContext();
                  
                  context->setContextProperty("cppInterface", &m_qmlCppMediator);
                  m_qmlCppMediator.setConnected(true);
                  
                  IcecastServer icecastServer(&m_qmlCppMediator);
                  
                  return app.exec(&#41;;
                  

                  }@

                  1 Reply Last reply Reply Quote 0
                  • M
                    mbrasser last edited by

                    Hi,

                    You should be able to get rid of the error by setting the context property before calling setMainQmlFile().

                    Regards,
                    Michael

                    1 Reply Last reply Reply Quote 0
                    • A
                      andre last edited by

                      Indeed: first setup the context with the mediator object, and then set the QML.

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post