PDA

View Full Version : MouseArea:weird behavior (mechanism) of onPressed



clarksuper0420
3rd September 2015, 09:44
Hi all,

For some reason, I need to propagate "Pressed event" to lower MouseArea. In the meanwhile, I still want to handle "Clicked event" after handling "Pressed event".
It turns out that I cannot achieve both criteria together.

If I set mouse.accepted = false during handling redBlock's onPressed() as example code below, I can successfully propagate "Pressed event" to blueBlock. However, this will disable the handling of "Clicked event" in redBlock which I don't think it makes any sense.

From QT document,
pressed(MouseEvent mouse):
When handling this signal, use the accepted property of the mouse parameter to control whether this MouseArea handles the press and all future mouse events until release.The default is to accept the event and not allow other MouseAreas beneath this one to handle the event. If accepted is set to false, no further events will be sent to this MouseArea until the button is next pressed.

I don't understand why they design like this. "If accepted is set to false, no further events will be sent to this MouseArea until the button is next pressed." doesn't make any sense to me. When you set mouse.accepted = false, you expect that the other mouse handler can take over this mouse event. Does anyone know why they design such weird mechanism for onPressed?



import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2

ApplicationWindow {
title: qsTr("Hello World")
width: 1280
height: 720
visible: true

Rectangle{
id: blueBlock
width: parent.width ; height: parent.height;
color: "blue"
MouseArea{
anchors.fill: parent
onPressed:{
console.log("Blue block is pressed")
}
onClicked: {
console.log("Blue block is clicked")
}
}
}
Rectangle{
id: redBlock
width: parent.width/2; height: parent.height/2
anchors.centerIn: parent
color: "red"
MouseArea{
anchors.fill: parent
onPressed:{
console.log("Red block is pressed")
mouse.accepted = false
}
onClicked: {
console.log("Red block is clicked")
}

}
}
}

anda_skoa
3rd September 2015, 10:55
If you only need the click in redBlock, maybe put that mouse are under the other and let the other propagate composed events?

Cheers,
_

clarksuper0420
3rd September 2015, 12:24
Hi Anda_Skoa,
Thanks. But what I need for redBlock is both "press" and "click".

The reason is a little bit long. But I am willing to tell you if you think that will help you to answer my question.

anda_skoa
3rd September 2015, 13:29
Hmm.

What if you don't let the redBlock MouseArea "ignore" the event but let its handlers just invoke both targets?

E.g. if a click on redBlock should trigger that MouseArea's onClicked and that of blueBlock, just call both target functions in redBlock?

Cheers,
_

clarksuper0420
3rd September 2015, 16:18
Actually, I cannot call blueBlock's pressed & clicked handler in redBlock because in my case, redBlock is larger than blueBlock. Clicking redBlock doesn't guarantee that the blueBlock should be clicked.
In order to explain this problem well, I need to refer my other post: http://www.qtcentre.org/threads/63582-z-order-for-mouseArea-doesn-t-work-in-ListView

My redBlock is ListView which has higher priority to receive mouse event. And moreover, it has larger area than its items. That means when I clicked ListView (redBlock), that doesn't guarantee blueBlock (items) must be clicked. I use Rectangle red & blue block to illustrate my question in this post so I can simplify my question. Which is unreasonable design of "If accepted is set to false, no further events will be sent to this MouseArea until the button is next pressed.".

I was trying to solve my problem by following ideas.
1. ListView get onPressed first. Set mouse.accepted = false so item's onPressed can be triggered.
2. Item's onPressed set a flag, called isHandlingItem, to true.
3. When ListView's onClicked get mouse event first. It can use the flag to know whether it should handle it or not
However, the ListView won't be able to receive onClicked because mouse.accepted = false will weirdly disable the other mouse event.

Anyway, this whole problem shouldn't be such complex if I can reserve the mouse priority between ListView and its items. And you helped me with that already. So I don't have to use onPressed to work around. So this onPressed problem is not critical anymore.

However. Still, I think the design of "If accepted is set to false, no further events will be sent to this MouseArea until the button is next pressed." doesn't fit instinct (or fit other mouseArea logic). So I was wondering if I understand it wrong or it is what it is.


I tried my best to explain the whole story well but I know it's not easy to understand it by reading my expression. Thank you very much for your time. I appreciate your kindly help.