Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to avoid QML error: “This is probably intended to be a signal handler but no signal of the target matches the name.”
Forum Updated to NodeBB v4.3 + New Features

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

Scheduled Pinned Locked Moved Solved QML and Qt Quick
5 Posts 2 Posters 1.5k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    rhvonlehe
    wrote on last edited by
    #1

    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"
            }
        }
    
    }
    
    jeremy_kJ 1 Reply Last reply
    0
    • R rhvonlehe

      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"
              }
          }
      
      }
      
      jeremy_kJ Offline
      jeremy_kJ Offline
      jeremy_k
      wrote on last edited by
      #2

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

      Asking a question about code? http://eel.is/iso-c++/testcase/

      1 Reply Last reply
      3
      • R Offline
        R Offline
        rhvonlehe
        wrote on last edited by
        #3

        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.

        jeremy_kJ 1 Reply Last reply
        1
        • R rhvonlehe

          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.

          jeremy_kJ Offline
          jeremy_kJ Offline
          jeremy_k
          wrote on last edited by jeremy_k
          #4

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

          Asking a question about code? http://eel.is/iso-c++/testcase/

          R 1 Reply Last reply
          1
          • jeremy_kJ jeremy_k

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

            R Offline
            R Offline
            rhvonlehe
            wrote on last edited by rhvonlehe
            #5

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

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved