Home > OS >  ContainsMouse gives incorrect value on parent change
ContainsMouse gives incorrect value on parent change

Time:10-03

In QML, the MouseArea's containsMouse property is supposed to return true when the enter image description here

Here is the code:

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    width: 800
    height: 500
    visible: true

    Rectangle {
        id: square
        width: 200
        height: 200
        focus: true
        color: my_mouse_area.containsMouse ? "blue" : "red"

        MouseArea {
            id: my_mouse_area
            anchors.fill: parent
            hoverEnabled: true
            onClicked: {
                my_mouse_area.x = 200
            }
        }

        Text {
            anchors.centerIn: parent
            text: my_mouse_area.containsMouse   ""
            font.pixelSize: 20
        }

        Keys.onPressed: {
            if(event.key === Qt.Key_Control){
                second_window.show()
                square.parent = second_window.contentItem
            }
        }
    }

    Window {
        id: second_window
        width: 400
        height: 400
        visible: false
    }
}

CodePudding user response:

The solution I came up with uses Timer, but with zero interval, thus zero flickering. You can try setting the interval to higher value, to see what is going on. The trick is to set the rectangle visibility dependent of the timer running using "visible: !tmr.running", and start the timer immediately after the parent change of the rectangle.

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    width: 800
    height: 500
    visible: true

    Rectangle {
        id: square
        width: 200
        height: 200
        focus: true
        color: my_mouse_area.containsMouse ? "blue" : "red"

        visible: !tmr.running

        Timer {
             id: tmr
             interval: 0
        }

        MouseArea {
            id: my_mouse_area
            anchors.fill: parent
            hoverEnabled: true
            onClicked: {
                my_mouse_area.x = 200
            }
        }

        Text {
            anchors.centerIn: parent
            text: my_mouse_area.containsMouse   ""
            font.pixelSize: 20
        }

        Keys.onPressed: {
            if(event.key === Qt.Key_Control){
                second_window.show()
                square.parent = second_window.contentItem
                tmr.start()
            }
        }
    }

    Window {
        id: second_window
        width: 400
        height: 400
        visible: false
    }
}

CodePudding user response:

I don't like my first solution, so I have made another, more sophisticated one, but this is not a pure QML solution. The trick is that on parent change you should call a C method where you send a mouse move event back to the mouse area, so it will re-evaluate the hovered aka containsMouse boolean. It is a nicer solution, but still a bit of a workaround.

Make sure you have a simple QObject derived class like MyObject with the following Q_INVOKABLE method:

class MyObject : public QObject
{
    Q_OBJECT

    //
    // constuctor and whatnot
    //

    Q_INVOKABLE void sendMouseMoveEventTo(QObject* item)
    {
        QEvent* e = new QEvent(QEvent::MouseMove);
        QCoreApplication::sendEvent(item, e);
    }
};

Make an instance of it in main.cpp, and set as context property, so you can reach it from QML:

MyObject myObject;
engine.rootContext()->setContextProperty("myObject", &myObject);

And finally in the QML Rectangle add this:

onParentChanged: {
    myObject.sendMouseMoveEventTo(my_mouse_area)
}
  • Related