Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

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.1

    Button {

    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.


  • Moderators

    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.html

    You 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.


  • Moderators

    Glad to hear :) All the best with your project!


Log in to reply