How to prevent scroll events from propagating to parent elements
-
I'm working on a project that's a bit complex and lengthy, so I've stripped it down to the most important parts to explain my problem here.
I need to create a page element that represents a page or tab in my application. This page should be able to hold multiple elements (e.g., buttons, combo boxes, text elements). To achieve this, I designed the page element to include a
ScrollView
, allowing vertical stacking and scrolling of its contents.Here's the code for the page element:
Item { id: root default property alias content: columnLayout.data property alias pageTitle: titleText.text implicitWidth: 300 implicitHeight: 300 Rectangle { anchors.fill: parent color: "white" // ScrollView to enable vertical scrolling for the page. ScrollView { anchors.fill: parent contentWidth: -1 // Disable horizontal scrolling contentHeight: columnLayout.height ColumnLayout { id: columnLayout anchors.fill: parent clip: true // Title text for the page. Text { id: titleText horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter color: "black" } } } } }
This implementation works well, and I can add as many elements as I want (e.g., buttons, combo boxes, text elements). However, there's an issue when I include another scrollable element, like a
ListView
, within this page.For example:
CustomPage { anchors.fill: parent // Many elements are placed here... ListView { width: parent.width height: 100 model: 50 delegate: Text { text: "Item " + index } } // Many elements are placed here... }
The problem occurs when scrolling with the mouse wheel. The
ListView
scrolls as expected, but when it reaches its limit (when it hits its vertical scroll limit), the parent page'sScrollView
starts scrolling instead.Technically, this might seem like normal behavior, but it's frustrating because I only want the page to scroll when the mouse leaves the
ListView
area and the user intends to scroll the main page. It is really annoying to be checking a list and all of sudden the main page starts to scroll. My guess is because the wheel event of the mouse is getting propagated to the parentScrollView
. But, maybe I am wrong.I would really appreciate some help on how to prevent this.
-
I did some more research and it seems this is the way to do it:
// This code must be placed directly in the ListView WheelHandler { acceptedDevices: PointerDevice.Mouse property int speed: 2 property Flickable flickable: parent.parent onWheel: (event) => { let scroll_flick = event.angleDelta.y * speed; if(flickable.verticalOvershoot != 0.0 || (scroll_flick>0 && (flickable.verticalVelocity<=0)) || (scroll_flick<0 && (flickable.verticalVelocity>=0))) { flickable.flick(0, (scroll_flick - flickable.verticalVelocity)); return; } else { flickable.cancelFlick(); return; } } }
Hope this helps someone.
-
I did some more research and it seems this is the way to do it:
// This code must be placed directly in the ListView WheelHandler { acceptedDevices: PointerDevice.Mouse property int speed: 2 property Flickable flickable: parent.parent onWheel: (event) => { let scroll_flick = event.angleDelta.y * speed; if(flickable.verticalOvershoot != 0.0 || (scroll_flick>0 && (flickable.verticalVelocity<=0)) || (scroll_flick<0 && (flickable.verticalVelocity>=0))) { flickable.flick(0, (scroll_flick - flickable.verticalVelocity)); return; } else { flickable.cancelFlick(); return; } } }
Hope this helps someone.
-