Diego
Diego

Reputation: 357

QML: Problems with mousearea overlapping

I have a QML application and problems with MouseAreas.

In a small test app, there is a red rectangle and when mouse enters this rect, a grey menu appears below (created with a Loader).

This grey menu must be open while mouse is over the red rectangle or the menu. For this purpose, I have 2 MouseAreas, 1 over the red rect and 1 over the menu. Both are 'hoverEnabled' and with 'enter' and 'exit' I control 'hoverDialog' and 'hoverTopZone'.

When both are false, it means that the mouse is out, so I close the menu (using a signal, the Loader gets inactive).

The timer is required since when passing from 'mouseAreaTopZone' to 'mouseAreaDialog' there is just a moment with 'hoverDialog' and 'hoverTopZone' are both false. Fixed with the timer.

In the middle of the menu there is a green rect, and (only) when mouse is over there, a yellow rect must be visible.

There is my problem. I have a MouseArea inside the green rect, but the yellow rect is not visible when required.

If I move 'rectGreen' below 'mouseAreaTopZone' and 'mouseAreaDialog' (that is, at the end of the file) I get the yellow rect visible when the mouse is over green rect, since its mouse area is then 'topmost'

BUT in this case, the menu dialog is closed, since when the mouse enters the MouseArea inside green rect, hoverDialog and hoverTopZone are false...

I hope U can understand my problem... Here is my code:

Test.qml

import QtQuick 2.5
import QtQuick.Controls 1.3
import QtQuick.Window 2.0

Item {
    width: 800
    height: 800

    Rectangle{
        id: rect
        anchors { top: parent.top; topMargin: 100; horizontalCenter: parent.horizontalCenter }
        height: 50; width: 50
        color: "red"

        MouseArea {
            anchors.fill: parent
            hoverEnabled: true
            onEntered: loader_dialog.active = true
        }
    }

    Loader {
        id: loader_dialog
        anchors { top: rect.bottom; horizontalCenter: rect.horizontalCenter}
        active: false
        sourceComponent: TestMenu {
            onClose: loader_dialog.active = false;
        }
    }
}

TestMenu.qml

import QtQuick 2.0

Rectangle {
    id: id_dialog

    signal close()

    width: 400
    height: 600

    color: "lightgrey"

    property bool hoverDialog: false
    property bool hoverTopZone: false

    function update() {
        if (!hoverDialog && !hoverTopZone)
            timer.start();
    }

    function check() {
        if (!hoverDialog && !hoverTopZone)
        {
            console.log("close");
            id_dialog.close();
        }
    }

    Timer {
        id: timer
        interval: 100
        running: false
        repeat: false
        onTriggered: check();
    }

    Rectangle {
        id: rectGreen
        width: 200; height: 100
        anchors.centerIn: parent
        color: "green"

        Rectangle {
            id: rectYellow
            anchors.centerIn: parent
            width: 50; height: 50
            color: "yellow"
            visible: false
        }

        MouseArea {
            anchors.fill: parent

            hoverEnabled: true
            onEntered: { rectYellow.visible = true; }
            onExited: { rectYellow.visible = false }
        }
    }

    MouseArea {
        id: mouseAreaTopZone
        anchors { bottom: parent.top; horizontalCenter: parent.horizontalCenter}
        width: 50; height: 50

        hoverEnabled: true
        onEntered: { hoverTopZone = true; id_dialog.update(); }
        onExited:  { hoverTopZone = false; id_dialog.update(); }
    }

    MouseArea {
        id: mouseAreaDialog
        anchors.fill: parent

        hoverEnabled: true
        onEntered: { hoverDialog = true; id_dialog.update(); }
        onExited: { hoverDialog = false; id_dialog.update(); }
    }
}

Thanks in advance, Diego

Upvotes: 1

Views: 1289

Answers (1)

Diego
Diego

Reputation: 357

Thanks Mark Ch for your help.

I need to close the dialog when the mouse exits, so I think I can not use 'Popup' control...

I solved the problem. Using only one variable to know if the mouse is over my dialog ('m_iNumHovered'), I add a reference every time I enter in a Mouse Area, and I decrease it when I exit. The key was to add/remove a reference in the MouseArea over the green rectangle, to keep it 'm_iNumHovered=true' (dialog visible)

New code for TestMenu.qml:

import QtQuick 2.0

Rectangle {
    id: id_dialog

    signal close()

    width: 400
    height: 600

    color: "lightgrey"

    property int m_iNumHovered: 0
    onM_iNumHoveredChanged: update();

    function update() {
        if (m_iNumHovered == 0)
            timer.start();
    }

    function check() {
        if (m_iNumHovered == 0)
            id_dialog.close();
    }

    Timer {
        id: timer
        interval: 100
        running: false
        repeat: false
        onTriggered: check();
    }

    MouseArea {
        id: mouseAreaTopZone
        anchors { bottom: parent.top; horizontalCenter: parent.horizontalCenter}
        width: 50; height: 50

        hoverEnabled: true
        onEntered: m_iNumHovered++;
        onExited: m_iNumHovered--;
    }

    MouseArea {
        id: mouseAreaDialog
        anchors.fill: parent

        hoverEnabled: true
        onEntered: m_iNumHovered++;
        onExited: m_iNumHovered--;
    }

    Rectangle {
        id: rectGreen
        width: 200; height: 100
        anchors.centerIn: parent
        color: "green"

        Rectangle {
            id: rectYellow
            anchors.centerIn: parent
            width: 50; height: 50
            color: "yellow"
            visible: false
        }

        MouseArea {
            anchors.fill: parent

            hoverEnabled: true
            onEntered: { m_iNumHovered++; rectYellow.visible = true; }
            onExited: { m_iNumHovered--; rectYellow.visible = false }
       }
    }
}

Upvotes: 0

Related Questions