Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to avoid QML error: “This is probably intended to be a signal handler but no signal of the target matches the name.”



  • I have working QML that has an ApplicationWindow with a Loader. The loader has a default qml file GameStart.qml representing a screen with some startup activities. For simplicity, say the 1st screen can navigate to the 2nd screen gamePlay.qml and the 2nd can navigate back to the 1st. The navigation is done by the loaded item emitting a signal that the ApplicationWindow has slots for. All that happens in the slots is the Loader's source gets modified.

    // RootWindow.qml
    import QtQuick          2.12
    import QtQuick.Controls 2.12
    import QtQuick.Window   2.12
    import QtQuick.Layouts  1.12
    ApplicationWindow {
        id:             mainWindow
        minimumWidth:   Math.min(215 * Screen.pixelDensity, Screen.width)
        minimumHeight:  Math.min(120 * Screen.pixelDensity, Screen.height)
        visible:        true
        color:          "turquoise"
    
        property string currentScreen: "GameStart.qml"
    
        Loader {
            id:             dynamicLoader
            anchors.fill:   parent
            source:         currentScreen
        }
    
        Connections {
            target: dynamicLoader.item
            function onPlayGame() {
                currentScreen = "GamePlay.qml"
                console.log("currentScreen: ", currentScreen)
            }
        }
        Connections {
            target: dynamicLoader.item
            function onEndGame() {
                currentScreen = "GameStart.qml"
                console.log("currentScreen: ", currentScreen)
            }
        }
    }
    

    The default screen and the other screen declare signals like this:

    // GameStart.qml
    import QtQuick 2.12
    import QtQuick.Controls 2.12
    import QtQuick.Layouts 1.12
    
    Item {
        id: gameStart
        anchors.top: parent.top
        height: parent.height
        width: parent.width
        signal playGame
    
        RowLayout {
            id: layout
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.verticalCenter: parent.verticalCenter
    
            RoundButton {
                id: playButton
                text: "Play"
                width: 40
                radius: 2
                font.pointSize: 12
                Layout.alignment: Qt.AlignVCenter
                onClicked: {
    //                var players = selector.playerArray
    //                for (var i =0; i < players.count; i++) {
    //                    console.log(players.itemAt(i).playerName)
    //                    game.addPlayer(players.itemAt(i).playerName)
    //                }
                    gameStart.playGame()
                }
            }
        }
    }
    

    Things work the way I expect them to, but there is a runtime error message that pops up that I'd rather not have:

    qrc:/qml/RootWindow.qml:25:5: QML Connections: Detected function "onPlayGame" in Connections element. This is probably intended to be a signal handler but no signal of the target matches the name.
    

    My guess is this happens because I use as the Connections target: dynamicLoader.item and that is not a specific object id, but rather a dynamically loaded object. I am not able to use e.g. gameStart or gamePlay as targets of the Connections in RootWindow.qml, however. Those IDs are not recognized within that file.

    I suspect I have not discovered the idiomatic way of doing this and my way is kludgey. What should I do to avoid this runtime message?

    EDIT: here's the GamePlay.qml file and also PlayerArea.qml

    //GamePlay.qml
    import QtQuick 2.12
    import QtQuick.Controls 2.12
    import QtQuick.Layouts 1.12
    import QtQml.Models 2.12
    import QtQml 2.12
    
    
    Item {
        id: gamePlay
        signal endGame
        property var playerArray : game.getPlayers()
    
        ListModel {
            id: playerLayoutModel
            ListElement {
                property var row: 1
                property var column: 0
            }
            ListElement {
                property var row: 1
                property var column: 2
            }
            ListElement {
                property var row: 0
                property var column: 1
            }
            ListElement {
                property var row: 2
                property var column: 1
            }
        }
    
        ColumnLayout {
            id: mainColumn
            spacing: 2
            anchors.fill: parent
            anchors.horizontalCenter: parent.horizontalCenter
    
            Rectangle {
                Layout.alignment: Qt.AlignHCenter
                height: 100
                width: 250
                color: "turquoise"
                RowLayout {
                    id: gameButtonsLayout
                    anchors.fill: parent
                    Button {
                        id: deal
                        Layout.preferredHeight: 50
                        Layout.preferredWidth: 80
                        text: "Deal"
                    }
    
                    Button {
                        id: end
                        Layout.preferredHeight: 50
                        Layout.preferredWidth: 80
                        text: "End Game"
                        onClicked: {
                            gamePlay.endGame()
                        }
                    }
    
                    Button {
                        id: save
                        Layout.preferredHeight: 50
                        Layout.preferredWidth: 80
                        text: "Save Game"
                    }
                }
            }
    
            Rectangle {
                Layout.fillHeight: true
                Layout.fillWidth: true
                anchors.horizontalCenter: Layout.horizontalCenter
                color: "turquoise"
    
                GridLayout {
                    id: gridnew
                    columns: 3
                    rows: 3
                    anchors.fill: parent
                    property var playerCnt: playerArray.length
    
                    Repeater {
                        model: playerLayoutModel
                        delegate: playerArea
                    }
    
                    Component {
                        id: playerArea
                        PlayerArea {
                            color: "red"
                            playerName: playerArray[index]
                            Layout.row: model.row
                            Layout.column: model.column
                            Layout.fillHeight: true
                            Layout.fillWidth: true
                            enabled: gridnew.playerCnt > index ? true : false
                            opacity: gridnew.playerCnt > index ? true : false
                        }
                    }
                }
    
                Component.onCompleted: {
                    console.log("rectangle containing grid size: ", height, width)
                    console.log("rectangle center: ", horizontalCenter, verticalCenter)
                }
            }
        }
    
    }
    
    // GamePlay.qml
    import QtQuick 2.12
    import QtQuick.Controls 2.12
    import QtQuick.Layouts 1.12
    
    Item {
        id: playerArea
        property string playerName
        property string cardText
        property string color
    
        Component.onCompleted: {
            var globalCoords = playerArea.mapToItem(gamePlay, x, y)
            console.log("playerArea.enabled: ", enabled)
            console.log("playerArea coords: ", x, y)
            console.log("area at coords: ", globalCoords.x, globalCoords.y)
        }
    
        ColumnLayout {
            //        Card {
            //        }
    
            //        Rectangle { // TODO remove when graphical card ready
            //            height: 20
            //            width: 20
            anchors.horizontalCenter: parent.horizontalCenter
            Label {
                color: playerArea.color
                height: 50
                width: 50
                text: cardText
            }
            //        }
    
    
            Label {
                id: nameLabel
                height: 50
                width: 50
                text: playerName
            }
    
            Button {
                id: playButton
                height: 50
                width: 50
                text: "Play Card"
            }
        }
    
    }
    


  • @rhvonlehe https://doc.qt.io/qt-6/qml-qtqml-connections.html#ignoreUnknownSignals-prop

    While the Loader is loading, Loader.item doesn't point to a valid object. As such, the signal expected by the Connections instance also won't exist.



  • I wouldn't have thought there would be a property to ignore a runtime error message. It definitely works, though. Thank you.

    There's a similar Stack Overflow message that you can answer and take credit for there if you like. I can't answer it myself for a day or two.



  • @rhvonlehe said in How to avoid QML error: “This is probably intended to be a signal handler but no signal of the target matches the name.”:

    I wouldn't have thought there would be a property to ignore a runtime error message.

    That's what Connections.ignoreUnknownSignals is. "If this property is set to true, such errors are ignored."
    Logging the condition, depending on the Qt Declarative version, is implemented as:

            } else if (!d->ignoreUnknownSignals
                                   && propName.startsWith(QLatin1String("on")) && propName.length() > 2
                                   && propName.at(2).isUpper()) {
                            qmlWarning(this) << tr("Detected function \"%1\" in Connections element. "
                                                   "This is probably intended to be a signal handler but no "
                                                   "signal of the target matches the name.").arg(propName);
                        }
                
    

    Or do you mean ignore warning messages in general? QLoggingCategory configuration can do that, as can qInstallMessageHandler.

    There's a similar Stack Overflow message that you can answer and take credit for there if you like. I can't answer it myself for a day or two.

    I never got into Stack Overflow point collecting. Thanks for the offer.



  • @jeremy_k
    "I never got into Stack Overflow point collecting. Thanks for the offer."

    I like you even more now.

    Marked as solved. I forgot to do this yesterday.


Log in to reply