Signal called from QML isn't connected to C++ slot, no errors given
-
I've been pouring over Qt documentation for 5 days straight and just spent literally all night trying to solve this one signal/slot error in a prototype, trying to understand Qt. I'm able to connect the first slot/signal but the other pair isn't working.
@Rectangle {
id: page
width: 1000
height: 1000
color: "#343434"signal readyToStartGame() RandomMoveButton{ anchors.left: startGame.right } Button { id: startGame width: 100 height: 50 Text{ text: "new game" anchors.centerIn: parent } MouseArea{ anchors.fill: parent onClicked: { readyToStartGame(); } } }
...
@My RandomMoveButton has a signal, and it's the one that's giving me problems. The signal above gives me no problems and connects to its slot just fine. Here is the QML file with the problem signal:
@
import GameController 1.0
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1Button {
signal clickedRandomMove() id: randomMove width: 100 height: 50 Text{ text: "random move" anchors.centerIn: parent } MouseArea{ anchors.fill: parent onClicked: { randomMove.clickedRandomMove() } }
}@
Here is the code that connects the signal and slot:
@
void initialize(){
QQuickView view;
view.setSource(QUrl::fromLocalFile("qml/PentagoQtRapidPrototype/RandomMoveButton.qml"));
QObject* object = view.rootObject();
QQuickItem* item = qobject_cast<QQuickItem*>(object);
QObject::connect(item, SIGNAL(clickedRandomMove()), this, SLOT(randomMove()));
}@
There are no errors or messages regarding this connection, but when the signal is fired (it definitely happens when I click the button), it doesn't go into the C++ slot. It just stops. I'm not making any threads (although I have tried going that route with the same results). It's worth noting that the initialize() is a member of a subclass. The parent class is a pure abstract base class that implements the slot. In other words, the "this" in the receiver argument in the QObject::connect call is a subclass, and randomMove() is a slot implemented in the pure abstract parent class. My problem is that randomMove() never gets called. I have spent 2 days on this one connection, reading every article on the internet I could find.
-
Hi, and welcome to the Qt Dev Net!
[quote]when the signal is fired (it definitely happens when I click the button)[/quote]How did you determine that the signal is definitely fired?
[quote author="badair" date="1390743626"]
@
void initialize(){
QQuickView view;
...
}
@
[/quote]The QQuickView is a local variable here -- it will be destroyed when initialize() returns. All its children (including your button) should be destroyed as well, meaning that the button should disappear and its connections should break.You'll need to allocate your QQuickView on the heap (call new QQuickView(parent)) to ensure it doesn't disappear.
How did you initialize your ready-to-start-game example?
By the way, there are other improvements you can make:
[quote]
@
Button {
...
MouseArea {...}
}
@
[/quote]
The Button type already listens for mouse events and emits a clicked() signal: http://qt-project.org/doc/qt-5/qml-qtquick-controls-button.htmlYou can remove your MouseArea and signal; just connect to the clicked() signal.
[quote]
@
Button {
Text{
text: "random move"
anchors.centerIn: parent
}
}
@
[/quote]The Button type already has a text field:
@
Button {
text: "random move"
}
@
[quote]
@
QObject* object = view.rootObject();
QQuickItem* item = qobject_cast<QQuickItem*>(object);
@
[/quote]rootObject() already returns a QQuickItem:
@
QQuickItem* item = view.rootObject();
@ -
Wow, thank you so much JKSH. That makes perfect sense. I fixed the problem by not instantiating a new QQuickView and instead passing the address of the original one as needed. If it weren't for your post, there is no telling how much longer it would've taken me to come to that conclusion. Our team has made a lot of progress and we have a better grasp of Qt.
For posterity:
My problem was that I was mistakenly instantiating a new view, which existed without being shown and only existed for a short time within a function. I was trying to connect a signal from the window that was already instantiated and shown. The QQuickView::setSource(...) method is not how you interact with a QML app that is already up and running. -
Glad to hear :) All the best with your project!