Change a state of Roundbutton from C++



  • Hello,

    I've a button with 3 states("A", "B", "C"), Starting state is "A".
    I verified that without the C++ code, just moving state in each press of the button the states are well define/working.

    When the button is pressed a C++ function is invoked and open QInputDialog. According to the answer i need to change the state of the button to "B" or to stay at state "A". (for now state "C" is not used).

    My problem, i'm unable to change the state !!! :-(.
    i've tried sending a signal from the C++ and catch it in the QML , i follow this directions:

    1. http://doc.qt.io/qt-5/qtqml-syntax-signals.html
    2. http://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html#attached-properties-and-attached-signal-handlers
    3. http://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html

    but none of them work on me.. i must be missing something but i can't figure out what... :-(

    did anybody can help??

    Thanks


  • Lifetime Qt Champion

    Hi,

    Please show us the code you wrote. Without that it's pretty much Crystal Ball Debugging (tm).



  • No Problem, here is the code:
    QML code :

    RoundButton {
    	id:                 BoxLeft
    	objectName:         "BoxLeft"
    	visible:            true		
    	state: "A"		
    
    	states: [
    		State {
    		name: "A"
    			PropertyChanges {
    				target: BoxLeft
    				onClicked :{
    					//state = "B"
    					_activeVehicle.A()}
    				buttonImage: "/qmlimages/ZoomMinus.svg"}
    		},
    		State {
    			name: "B"
    			PropertyChanges {
    				target: BoxLeft
    				onClicked: {
    					//state = "C"
    					_activeVehicle.B()}
    				buttonImage: "/qmlimages/ZoomPlus.svg" }
    			},
    		State {
    			name: "C"
    			PropertyChanges {
    				target: BoxLeft
    				enabled: false				
    			}
    		}
    	]
    }
    

    C++ code:

    void Vehicle::A() {
     qDebug() << "Enter A";
    int randomNumber = (qrand() % 9000)+1000;
    bool ok;
    userTry = QInputDialog::getInt(0, "Random Code", "enter 4 digit number", 0, 1000, 9999, 1, &ok);
    if (userTry !=randomNumber)
      return; //Don't change button state
    
    emit buttonStateChange(1); //1 is represent for "B" state
    }
    

    _activeVehicle is a C++ object that is define like this(in the QML):

    property var    _activeVehicle:             QGroundControl.multiVehicleManager.activeVehicle
    

    I don't add the B() code because i don't get to it.
    I can see the "Enter A" and as you can see in the QML i verified that if i don't use the C++ code the state is change and working.

    I also deleted the code that i've added in order to receive the signal because it doesn't work :-(

    Again, any help will be highly appreciated and surly be used by future QT/QML users.

    @SGaist if more info is needed, just ask.

    Thanks



  • @Eyal-Erez It's a bit difficult to follow what you're doing with your code. In a simple situation we have a c++ object, e.g. 'backend'. It's been set as a context property.

    Backend backend;
    QQmlApplicationEngine* engine{new QQmlApplicationEngine()};
    QQmlContext* ctx{engine->rootContext()};
    ctx->setContextProperty("backend", &backend);
    

    After that it's visible as a global object named 'backend' in QML.
    Then in QML you call a method:

    backend.mySlotWhichEmitsASignal()
    

    In QML you must have

    Connections {
    target: backend
    onButtonStateChanged: console.log(buttonState)
    }
    

    This works if buttonState is a property in Backend or if buttonStateChanged is a signal with one parameter named 'buttonState'.

    You can do it even more simple way by binding a qml property with backend.buttonState property:

    Item{
    property int btnState: backend.buttonState
    onBtnStateChanged: console.log(btnState)
    }
    So there's no need to catch the signal manually at all. This works automatically if Backend and its property is written correctly.



  • @Eeli-K
    Yes i agree, i'm adding a code to an Open-Source QGC(https://github.com/mavlink/qgroundcontrol) so i'm (still) having limited knowlage of the code(both C++ and QML).
    For example they are calling:
    qmlRegisterUncreatableType<Vehicle> ("QGroundControl.Vehicle", 1, 0, "Vehicle", "Reference only");
    and in most tutorials they ask to call qmlRegisterType.

    Anyway, what solve my problem is the use of:
    propery string(!!!not QString!!!) btnState: _activeVehicle ? _activeVehicle.myBtnState :"A"
    state: btnState
    and of course setting the Q_PROPERTY with the read,write and notify function.

    Thank you so much for the help... Hope that it will help others in the future..

    Cheers



  • @Eyal-Erez Nice. It's even shorter if you leave 'property string btnState' out and use directly

    state: _activeVehicle ? _activeVehicle.myBtnState :"A"
    


  • @Eeli-K Correct :-)
    Wow i don't know if it good or bad that i just spent almost 2 days for less than 10 rows of code :-)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.