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. Calling Component destroy with a Menu open crashes app on Mac only (even if Menu is dismissed explicitly)
Forum Updated to NodeBB v4.3 + New Features

Calling Component destroy with a Menu open crashes app on Mac only (even if Menu is dismissed explicitly)

Scheduled Pinned Locked Moved QML and Qt Quick
1 Posts 1 Posters 801 Views 1 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.
  • Q Offline
    Q Offline
    qt_sur
    wrote on last edited by
    #1

    Hi,

    I recreated my issue on a sample app. I need to add several clickable components to a Rectangle, which all show Menu items on clicks. But some times, I need to remove everything from the UI.

    1. If I "destroy" the component while one of the components inside the Rectangle has the menu popped visible, the app crashes <-- this itself is probably a bug

    2. I fixed this on Windows by explicitly closing/dismissing the Menu before deleting the component. But it still crashes on Mac

    3. Destroying the components separately didn't make any difference either.

    Here are my two QML files:

    main.qml

    @import QtQuick 2.2
    import QtQuick.Controls 1.1

    ApplicationWindow {
    visible: true
    width: 600
    height: 600

    Rectangle {
        id: rootRectangle
    
        property Rectangle contentRectangle: null   // this is the Rectangle which will have all the "ClickableRect.qml" components added dynamically
        property Menu lastMenuHandle: null          // this will be set whenever the Menu with ClickableRect is invoked
    
        Button {
            id: button
            anchors.top: parent.top
            text: "Create Menu components"
    
            onClicked: {
                rootRectangle.addClickableRects();
            } // onClicked
        } // Button
        Label {
            anchors.top : button.bottom
            text: "After creating the components, click one of them to pop up the menu, to recreate the crash.\nLeave the menu open for 5 seconds. App will try to remove the components from the UI"
        }
    
        Timer {
            id: uiClearTimer
            interval: 5000          // have to click the red component before this 5 seconds, just to create this edge case
            onTriggered: {
                console.log("uiClearTimer - onTriggered");
                if (rootRectangle.contentRectangle !== null ) {
    
                    if ( rootRectangle.lastMenuHandle !== null && rootRectangle.lastMenuHandle.__popupVisible ) {
                        console.log ("Menu found open before destroying the component - closing it first");
                        rootRectangle.lastMenuHandle.__dismissMenu();
                        //rootRectangle.lastMenuHandle.__closeMenu(); // <-- close menu didn't make any difference
                    }
    
                    // NOTE: The following destroy calls go through (i.e prints out) but it crashes, if anyone of them had the menu opened
                    var i = 0;
                    var currChild;
                    for (i=0; i<rootRectangle.contentRectangle.children.length; i++) {
                        console.log("Destroying child component #" + i);
                        currChild = rootRectangle.contentRectangle.children[i];
                        currChild.destroy();
                    }
    
                    console.log("Destroying content rectangle");
                    // NOTE: Even if the containing rectangle isn't destroyed specifically, the child destroy calls are enough to crash the app
                    rootRectangle.contentRectangle.destroy(); // <-- this function crashes the app on MAC only, if ONE of the ClickableRect component within it has the menu already opened.
    
                    rootRectangle.contentRectangle = null;
                }
            }
        }
    
    
        function addClickableRects() {
            // first create the Rectangle
            if (rootRectangle.contentRectangle === null ) {
    
                rootRectangle.contentRectangle = Qt.createQmlObject("import QtQuick 2.0; Rectangle{anchors.fill: parent; color:\"yellow\"; border.width: 10 }", rootRectangle);
                if (rootRectangle.contentRectangle === null ) {
                    console.log(" ERROR - couldn't create contentRectangle");
                    return;
                }
                // Now loop and add 5 "ClickableRect.qml" component to rootRectangle.contentRectangle
                var i;
                for (i=0; i<5; i++ ) {
                    var clickableComp = Qt.createComponent("ClickableRect.qml");
    
                    if (clickableComp.status === Component.Ready) {
                        var clickableObject = clickableComp.createObject(rootRectangle.contentRectangle, {"x":i*60, "y":100, "parentRect":rootRectangle});
                    } else {
                        console.log(" ERROR - couldn't create object");
                        return;
                    } // else
                } // for
            } else {
                console.log(" ERROR - components are already created");
            }
    
            uiClearTimer.restart();
        } // addComponents
    
    } // rootRectangle
    

    }
    @


    ClickableRect.qml

    @import QtQuick 2.0
    import QtQuick.Controls 1.1

    Rectangle {

    property Rectangle parentRect: null // this will be passed as an arg when component is being created. So that the menu handle be set properly
    // expose the menuHandle so that it can be closed from main.qml
    //property Menu menuHandle: functionMenu
    
    color: "red"
    width: 50
    height: 50
    border.width: 10
    
    MouseArea {
        anchors.fill: parent
        onClicked: {
            // just pop open the menu
            functionMenu.popup();
        }
    }
    
    Menu {
        id: functionMenu
        MenuItem {
            text: "Function 1"
        }
    
        on__PopupVisibleChanged: {
            if ( __popupVisible) {
                // update the handle to the tabView so that it is closed if the tabView removes these PaletteItem ui objects
                parentRect.lastMenuHandle = functionMenu;
            }
        } // on__popupVisibleChanged
    }
    

    }
    @

    The fact that workaround is fine on Windows but not on Mac, makes me guess that this is probably a bug. But I'm hoping that there is some sort of work around for the time being. Any feedback would be really helpful.

    Thanks.

    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