Solved 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 theSwitchButton
, 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 thegeneratorPower()
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