Reputation: 11
I have two rectangles and i want them to send mouseevent to each other while moving mouse with pressed mouse button. See my example
Rectangle {
x: 100
width: 30
height: 30
color: "red"
MouseArea {
hoverEnabled: true
propagateComposedEvents: true
anchors.fill: parent
onMouseXChanged: console.log("red changed" + mouseX)
}
}
Rectangle {
x: 130
width: 30
height: 30
color: "green"
MouseArea {
hoverEnabled: true
propagateComposedEvents: true
anchors.fill: parent
onMouseXChanged: console.log("green changed"+ mouseX)
}
}
Everything works fine when i just move mouse between rectangles. But when i try to pres mouse button and then move - only one rectangle receive events. Is there a way to make it work with button pressed?
P.S. Initial problem, of course, is not with rectangles. Im trying to make combobox work quicker, when you need just one press to open popup and move cursor to item you want to select. But i can find a way to move press event from combobox input to popup. I think example i showed above is the right one to understand the problem.
Upvotes: 1
Views: 2493
Reputation: 2051
The problem is that once a button is pressed, the MouseArea
holds the mouse events even if we move outside the area. Then the other MouseArea
is not able to catch the mouse events.
The only solution I can imagine is to manage the change of position globally so that each MouseArea
receives the positionChange
signal from any other MouseArea
and individually decides whether an action is needed or not (See mapFromItem for position mapping):
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 500
height: 500
signal globalPositionChanged(var item, var position)
Rectangle {
id: rect1
x: 100
width: 30
height: 30
color: "red"
MouseArea {
hoverEnabled: true
propagateComposedEvents: true
anchors.fill: parent
clip: true
onPositionChanged: {
globalPositionChanged(rect1, mouse)
}
Component.onCompleted: {
globalPositionChanged.connect(handlePositionChange)
}
function handlePositionChange(item, position) {
var localPos = toLocalePosition(rect1, item, position)
if (localPos) {
// we are in the red rectangle
console.log("red", localPos.x, localPos.y)
}
}
}
}
Rectangle {
id: rect2
x: 130
width: 30
height: 30
color: "green"
MouseArea {
hoverEnabled: true
propagateComposedEvents: true
clip: true
anchors.fill: parent
onPositionChanged: {
globalPositionChanged(rect2, mouse)
}
Component.onCompleted: {
globalPositionChanged.connect(handlePositionChange)
}
function handlePositionChange(item, position) {
var localPos = toLocalePosition(rect2, item, position)
if (localPos) {
// we are in the green rectangle
console.log("green", localPos.x, localPos.y)
}
}
}
}
function toLocalePosition(toItem, fromItem, position) {
// return the local position if inside item, or null if outside
var localPos = toItem.mapFromItem(fromItem, position.x, position.y)
if (localPos.x >= 0
&& localPos.y >= 0
&& localPos.x <= toItem.width
&& localPos.y <= toItem.height) {
return localPos
}
return null
}
}
I'm not 100% convinced about this answer. There are probably better ways to do it, but I think it fixes your problem.
Upvotes: 3