Planned maintenance has been done but it did not solve the problem. So work will continue on this and a new time for trying updates will be announced asap.

QML Signal/C++ Slot connect successful, but no result when signal emitted?



  • Hello everyone - I'm having an issue with a slot not being called despite a successful connection between the QML signal and the C++ slot.

    I have a custom QML on/off type of switch that looks like this.

    Rectangle {
        id: buttonRoot
        border.color: colorMain
        color: "#000000"
        anchors.horizontalCenter: parent.horizontalCenter
        
        property bool on: false
        
        function switchState() {
            if(on === true) {
                topHalf.color = "#8d8d8d"
                bottomHalf.color = "#5e5e5e"
                topHalfLabel.text = ""
                bottomHalfLabel.text = "OFF"
                on = false
            }
            else {
                topHalf.color = "#5e5e5e"
                bottomHalf.color = "#00FF11"
                topHalfLabel.text = "ON"
                bottomHalfLabel.text = ""
                on = true
            }
        }
        
        MouseArea {
            id: mouseArea
            anchors.fill: parent
            onClicked: switchState()
        }
        
        Column {
            anchors.centerIn: parent
            
            Rectangle {
                id: topHalf
                color: "#8d8d8d"
                width: buttonRoot.width
                height: buttonRoot.height / 2
                
                GlowingLabel {
                    id: topHalfLabel
                    color: "white"
                    font.pixelSize: 30
                    anchors.centerIn: parent
                }
            }
            
            Rectangle {
                id: bottomHalf
                color: "#5e5e5e"
                width: buttonRoot.width
                height: buttonRoot.height / 2
                
                GlowingLabel {
                    id: bottomHalfLabel
                    text: qsTr("OFF")
                    color: "white"
                    font.pixelSize: 30
                    anchors.centerIn: parent
                }
            }
        }
    }
    

    This switch is used in a few different places, so I just put it in its own QML file, and then when I want to use it I just declare SwitchButton{} and change the dimensions if I need to.

    What I'm trying to do now is put an extra MouseArea on an instance of the SwitchButton, so when the button is clicked, not only does it turn on/off, but also emits a signal that is captured by a slot backend. The backend slot should change labels on the QML front end, for example: Pressure should go from 0 PSI in an off state, to 64 PSI in an on state.

    Here is what my instance of the SwitchButton looks like:

                SwitchButton {
                    id: generatorSwitch
                    objectName: "generatorSwitch"
                    width: 120
                    height: 145
                    
                    signal qmlSignal(bool generatorState)
                    
                    MouseArea {
                        anchors.fill: parent
                        propagateComposedEvents: true
                        onClicked: {
                            mouse.accepted = false
                            generatorSwitch.qmlSignal(generatorSwitch.on)
                        }
                    }
                }
    

    As you can see, qmlSignal(bool generatorState) sends whether the generator switch is ON/OFF to the backend code.

    In the C++ backend, I'm creating a QQmlComponent with the parent file, passing this object to a class which handles the changing of the ON/OFF values (GeneratorControl), and then forming a connection between the signal and slot.

        // Hook up signals and slots for integration with QML
        QQmlComponent component(&engine, QUrl("qrc:/qml/root.qml"));
        if(component.status() == component.Ready) {
            QObject* object = component.create();
    
            // GENERATOR ON/OFF SWITCH
            GeneratorControl generatorControl(object);
            QObject* generatorSwitch = object->findChild<QObject*>("generatorSwitch");
            bool res = QObject::connect(generatorSwitch, SIGNAL(qmlSignal(bool)),
                             &generatorControl, SLOT(generatorPower(bool)));
            qDebug() << res;
        }
    

    Here is the slot inside of the GeneratorControl instance, which should at least print either "power on" or "power off" when the switch is clicked in QML.

    void GeneratorControl::generatorPower(bool powerState)
    {
        if(powerState == true)
        {
            qDebug() << "power on";
            powerOnGenerator();
        }
        else
        {
            qDebug() << "power off";
            powerOffGenerator();
        }
    }
    

    However, nothing is printed out. The connection between the signal and slot is successful - the result of res is true, and I get no signal/slot connection errors in the console. But the code inside of the generatorPower() slot is never executed when flipping the switch ON/OFF.

    Any ideas? I think it might have something to do with the two MouseArea on the QML switch, but I'm not sure.

    Thank you.



  • Could it be because your GeneratorControl object is in the scope of the "if" statement, and therefore no longer exists when the scope terminates ?



  • @mranger90 That was it! I got around this by using a Qt smart pointer to control the scope:

        // Hook up signals and slots for integration with QML
        QQmlComponent component(&engine, QUrl("qrc:/qml/hep.qml"));
        QObject* generatorSwitch;
        QScopedPointer<GeneratorControl> generatorControl;
        if(component.status() == component.Ready) {
            QObject* object = component.create();
    
            // GENERATOR ON/OFF SWITCH
            generatorControl.reset(new GeneratorControl(object));
            generatorSwitch = object->findChild<QObject*>("generatorSwitch");
            bool res = QObject::connect(generatorSwitch, SIGNAL(qmlSignal(bool)),
                             generatorControl.data(), SLOT(generatorPower(bool)));
            qDebug() << res;
        }
    


  • @jjgccg said in QML Signal/C++ Slot connect successful, but no result when signal emitted?:

    That was it!

    Glad your issue is solved. Please don't forget to mark you post as such. Thanks


Log in to reply