[SOLVED] How to make a menu (or anything) vanish / animate state using QML timers when not being interacted with?



  • Hi guys,

    Im a a complete newbie so apologies for the basic questions, however I have had a hunt and am yet to spot answers to the things which stump me. I'm from a front end background rather than a C++ background.

    I have a menu, it opens and closes on a click of the menu icon and has a variety of objects you can hover over and click etc and it closes on the click of the menu icon.

    Now, if the mouse moves away from the menu without clicking anything, I want to close the menu after a few seconds using a timer.

    So my file has a menu with many rectangles used as menu buttons inside it each with their own onhover and onclick and that overall QML file has two states for default (menu closed) and State1 (for menu opened).

    I've looked into timers and the basic principle makes sense, however I am unsure how to tell the timer to trigger when no item on the menu is hovered or clicked AND unsure how to make the timer trigger a state change although I am guessing that is similar to a onClick action using if, else etc?

    Thank you again for your help!


  • Moderators

    Not sure if that would work, you'll have to check if events propagate well. But here's an idea that might be elegant and easy:

    create a MouseArea on top of the whole menu

    make it hoverable

    implement "onEntered" and "onExited" slots

    in "onEntered" turn the timer off

    in "onExited" turn the timer on

    in Timer, implement "onTriggered" to change the state of the menu

    Plus of course set amount of time to count etc.

    The only problem that I expect here is that hover events will not get propagated properly. One way out would be not to accept the event inside the menu. Anyway, try this first, if this does not work, report back, I've got few more ideas up my sleeve :)



  • Make sure your MouseArea on top of the whole menu has a lower z-index.



  • Hi sierdzio

    Thanks do much for answering.

    I actually started working in a method pretty much like that. I have yet to be able to get the timer to respond to the onExited event. I tried getting the onExited to effect something else (change the state of the menu which just bypasses the timer) but it also didnt seem to respond at all. I suspect there must be something underlying in my code which needs addressing.

    I placed a mousearea over everything (lets ignore that that ought to cover the menu's functions for now) and I gave it the lines:

    hoverEnabled: true
    onExited: menu.state = ""

    Which I thought would trigger the menu to change state on exit. Do I need an onEntered statement to use an onExited? I suspect my issues getting the timer to work are because the base onExited element has decide to run off to join the circus rather than running.

    If I can get onExited doing something at all I can then try again with the timer method!

    Thanks again for your help.



  • Here a small example that shows the usage of nested mouse areas and timers.
    @
    import QtQuick 1.1

    Item {
    width: 640
    height: 480

    Rectangle {
        id: rectangle
    
        anchors.centerIn: parent
        width: 320
        height: 120
    
        color: "blue"
    
        state: "normal"
        states: [
            State {
                name: "normal"
            },
            State {
                name: "active"
                PropertyChanges { target: rectangle; color: "red" }
            }
        ]
    
        Item {
            id: content
    
            anchors.fill: parent
            z: rectangle.z + 1
    
            MouseArea {
                anchors.fill: parent
    
                onClicked: {
                    rectangle.rotation += 90;
                }
            }
        }
    
        MouseArea {
            anchors.fill: parent
    
            hoverEnabled: true
    
            onEntered: {
                timer.stop();
                rectangle.state = "active";
            }
            onExited: {
                timer.restart();
            }
        }
    
        Timer {
            id: timer
    
            interval: 500
    
            onTriggered: {
                rectangle.state = "normal";
            }
        }
    }
    

    }
    @



  • Thanks Lukas, that's very concise.

    Perhaps onEntered is needed and I oversimplified, will implement your method and post my results.

    Thanks again,



  • onEntered is not needed for onExited to work. It most probably didn't work for you because either the MouseArea was covered by an item with an higher z-index or you had an syntax error in your event handler.



  • It turned out my mousearea had an opacity, which must have snuck in during a copy/paste while I was exploring methods. I kept looking for syntax errors and missed something obvious.

    Good to see someone else had the same idea of how to do this and such a good clean example set of code. I am sure this will help others as well.

    Thanks!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.