MouseArea clicks don’t work on a dynamically Created QML component

I am trying to create a custom tab with buttons that is created after a user has successfully logged in. The creation of the dynamic component works well but i seem to have issues with the onClicked signal inside the mouse area of the custom button.

If i don’t dynamically create the Application.qml the custom buttons work perfectly.
I cant seem to find the issue and since i am new to coding in qt i am sure i have missed something. Here is the code:

CustomTabButton.qml

import QtQuick 6.2

Rectangle{
    id: buttonRect

    width: 100
    height: 20
    radius: 2

    color: "#B2BEB5"

    signal buttonClicked

    Component.onCompleted:{
        buttonRect.buttonClicked.connect(mouseArea.onClicked);
    }

    Text{
        id: buttonText

        anchors.centerIn: parent
        text: qsTr("TESTING")
    }

    MouseArea{
        id: mouseArea

        anchors.fill: parent
        cursorShape: Qt.PointingHandCursor
        hoverEnabled: true

        onClicked: { console.log("NOT WORKING"); } //buttonRect.buttonClicked()
    }

}

CustomTab.qml

import QtQuick 6.2

Row{
    id: tabRow

    spacing: 2
    anchors.top: parent.top
    anchors.left: parent.left

    property int tabIndex

    CustomTabButton{
        id: firstButton

        onButtonClicked: {

            tabIndex = 0;
            console.log("first button clicked");

        }

    }
    CustomTabButton{
        id: secondButton

        onButtonClicked: {
            tabIndex = 1;
            console.log("second button clicked");

        }

    }

    Rectangle{
        id: underline

        width: 100
        height: 2
        color:"cyan"
        anchors.top: parent.bottom
        property real targetX: tabRow.tabIndex * underline.width

        NumberAnimation on x{
            duration: 200;
            to: underline.targetX;
            running: underline.x !== underline.targetX;
        }
    }

}

Code in Login.qml for the creation

Connections{
        target: db

        function onWrongLogin() {
            wrongLoginText = true
        }

        function onRightLogin(){

            var component = Qt.createComponent("Application.qml");
            //appWindow is the Window in main.qml  it only has Login in it
            var application = component.createObject(appWindow,{ width: 
                             appWindow.width, height:appWindow.height});

            if(application === null)
                console.log("Error creating object");

            login.destroy();

        }
    }

Application.qml

import QtQuick 6.2
import QtQuick.Controls

Item {
    id: applicationItem

    visible: true

    CustomTab{
        enabled: true
    }

}


  • In your CustomTabButton.qml code, can you explain your Component.onCompleted function? It looks like you are creating a signal loop where the mouseArea.onClicked calls buttonRect.buttonClicked, and then buttonRect.buttonClicked calls mouseArea.onClicked. I don’t know if that’s causing your problem, but it clearly looks wrong.

    – 

  • Oh i forgot to remove that code. In documentation it said to connect signals from dynamically created objects use the connect method. It was just a wild thing i did thinking it might fix the issue.

    – 

  • Out of curiosity, why are you creating a custom button from a rectangle, rather than inheriting from qml’s ‘Button’ type? If it’s just an exercise in qml coding, then I understand.

    – 

  • Yes for learning and knowing exactly how the button works. I will try it with a button type too to see the difference in them!

    – 

Thanks to the comment of JarMan opening my eyes I Fixed the issue. You need to connect the clicked signal from the MouseArea to a slot(function) and the function is called when the signal is emitted.

CustomTab.qml

import QtQuick 6.2

Rectangle{
   id: buttonRect

   width: 100
   height: 20
   radius: 2

   color: "#B2BEB5"

   function showClicked(){
       console.log("WORKING")
   }

   //signal buttonClicked

   Text{
       id: buttonText

       anchors.centerIn: parent
       text: qsTr("TESTING")
   }

   MouseArea{
       id: mouseArea

       anchors.fill: parent
       cursorShape: Qt.PointingHandCursor
       hoverEnabled: true

       Component.onCompleted:{
           mouseArea.clicked.connect(showClicked);
       }
       
       onClicked: { console.log("NOT WORKING"); } //buttonRect.buttonClicked()
   }

}

A signal can be connected to another signal or a slot.

You tried connecting it to a signal handler (more information here : The QML Reference, Signal attributes).

The correct syntax would be:

buttonRect.buttonClicked.connect(mouseArea.clicked); // not onClicked

What you most likely wanted was connecting the other way around (like you did in your answer):

mouseArea.buttonClicked.connect(buttonRect.clicked); // specifying buttonRect here is superfluous

What you should actually do is not doing an imperative connection but just doing it declaratively and directly emitting the signal:

MouseArea{
    anchors.fill: parent
    cursorShape: Qt.PointingHandCursor
    hoverEnabled: true

    onClicked: buttonRect.clicked()
}

I also agree with @Mark that using a Button would be preferred.

Leave a Comment