ScrollView interfering with MouseArea and/or MouseEvents
-
I have a ChartView with a Mouse area and custom script for zooming and panning on the chart. It work good on it is own but when I wrap the whole thing in a ScrollView ,(I can have arbitrarily many charts visible on the screen) it probably interferes with the mouse event handling and the scripts won't work . Below is a standalone demonstration of the problem;
import QtQuick 2.11 import QtQuick.Window 2.11 import QtCharts 2.2 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.4 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") ScrollView { id: scrollView anchors.fill : parent z : -1 clip: true; ScrollBar.vertical.policy : ScrollBar.AlwaysOn ScrollBar.horizontal.policy: ScrollBar.AlwaysOff ChartView { id: df antialiasing: true width : Math.max (implicitWidth ,scrollView.availableWidth ) height: Math.max(implicitWidth , scrollView.availableHeight) LineSeries { name: "LineSeries" XYPoint { x: 0; y: 0 } XYPoint { x: 1.1; y: 2.1 } XYPoint { x: 1.9; y: 3.3 } XYPoint { x: 2.1; y: 2.1 } XYPoint { x: 2.9; y: 4.9 } XYPoint { x: 3.4; y: 3.0 } XYPoint { x: 4.1; y: 3.3 } } Rectangle { id: zoomRect color: "black" opacity: 0.6 visible: false } Rectangle { id: scrollRect visible: false } MouseArea { anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.AllButtons onPressed: { if (mouse.button == Qt.LeftButton) { zoomRect.x = mouseX; zoomRect.y = mouseY; zoomRect.visible = true; } else if(mouse.button == Qt.RightButton) { df.zoomReset(); } if (mouse.button == Qt.MiddleButton) { scrollRect.x = mouseX; scrollRect.y = mouseY } } onMouseXChanged: { zoomRect.width = mouseX - zoomRect.x if ((mouse.buttons & Qt.MiddleButton) == Qt.MiddleButton) { df.scrollLeft(mouseX - scrollRect.x); df.scrollUp(mouseY- scrollRect.y); scrollRect.x = mouseX; scrollRect.y = mouseY; } } onMouseYChanged: { zoomRect.height = mouseY - zoomRect.y } onReleased: { if (mouse.button == Qt.LeftButton) { df.zoomIn(Qt.rect(zoomRect.x, zoomRect.y, zoomRect.width, zoomRect.height)); zoomRect.visible = false console.log ("mouse released") console.log (zoomRect.x , zoomRect.y , zoomRect.width , zoomRect.height) } } } } } }Without scroll view in onRelease handler of the MouseArea, it correctly prints the x,y position and the width&height of the zoom rectangle. with scroll view width&height prints out at zero and I notice a stutter when drawing the rectangle on screen.
Is there a way to disable to mouse events intercepted by the scroll view ?
Thanks in advance; -
I have a ChartView with a Mouse area and custom script for zooming and panning on the chart. It work good on it is own but when I wrap the whole thing in a ScrollView ,(I can have arbitrarily many charts visible on the screen) it probably interferes with the mouse event handling and the scripts won't work . Below is a standalone demonstration of the problem;
import QtQuick 2.11 import QtQuick.Window 2.11 import QtCharts 2.2 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.4 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") ScrollView { id: scrollView anchors.fill : parent z : -1 clip: true; ScrollBar.vertical.policy : ScrollBar.AlwaysOn ScrollBar.horizontal.policy: ScrollBar.AlwaysOff ChartView { id: df antialiasing: true width : Math.max (implicitWidth ,scrollView.availableWidth ) height: Math.max(implicitWidth , scrollView.availableHeight) LineSeries { name: "LineSeries" XYPoint { x: 0; y: 0 } XYPoint { x: 1.1; y: 2.1 } XYPoint { x: 1.9; y: 3.3 } XYPoint { x: 2.1; y: 2.1 } XYPoint { x: 2.9; y: 4.9 } XYPoint { x: 3.4; y: 3.0 } XYPoint { x: 4.1; y: 3.3 } } Rectangle { id: zoomRect color: "black" opacity: 0.6 visible: false } Rectangle { id: scrollRect visible: false } MouseArea { anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.AllButtons onPressed: { if (mouse.button == Qt.LeftButton) { zoomRect.x = mouseX; zoomRect.y = mouseY; zoomRect.visible = true; } else if(mouse.button == Qt.RightButton) { df.zoomReset(); } if (mouse.button == Qt.MiddleButton) { scrollRect.x = mouseX; scrollRect.y = mouseY } } onMouseXChanged: { zoomRect.width = mouseX - zoomRect.x if ((mouse.buttons & Qt.MiddleButton) == Qt.MiddleButton) { df.scrollLeft(mouseX - scrollRect.x); df.scrollUp(mouseY- scrollRect.y); scrollRect.x = mouseX; scrollRect.y = mouseY; } } onMouseYChanged: { zoomRect.height = mouseY - zoomRect.y } onReleased: { if (mouse.button == Qt.LeftButton) { df.zoomIn(Qt.rect(zoomRect.x, zoomRect.y, zoomRect.width, zoomRect.height)); zoomRect.visible = false console.log ("mouse released") console.log (zoomRect.x , zoomRect.y , zoomRect.width , zoomRect.height) } } } } } }Without scroll view in onRelease handler of the MouseArea, it correctly prints the x,y position and the width&height of the zoom rectangle. with scroll view width&height prints out at zero and I notice a stutter when drawing the rectangle on screen.
Is there a way to disable to mouse events intercepted by the scroll view ?
Thanks in advance;Hi @hsolter
You can do for example:ScrollView { id: scrollView ... Component.onCompleted: contentItem.interactive = false .... }Or dynamically change
interactive, etc... -
Wow. Works like a charm. of course in that case I can't scroll by mouse wheel and have to
scroll by moving the vertical scroll bar. I wonder that's the right way??@hsolter
Scroll by wheel just works fine, even ifinteractiveis false. Interactive only concerns the flick action ofFlickable. Have you tried? -
@hsolter
Scroll by wheel just works fine, even ifinteractiveis false. Interactive only concerns the flick action ofFlickable. Have you tried?@Diracsbracket said in ScrollView interfering with MouseArea and/or MouseEvents:
@hsolter
Scroll by wheel just works fine, even ifinteractiveis false. Interactive only concerns the flick action ofFlickable. Have you tried?Yup I've tried it at the original code .With your modification it does not work anymore. if I remove the modification, scroll by wheel works as usual. Maybe scrolling by wheel means flicking in some sense?
-
@Diracsbracket said in ScrollView interfering with MouseArea and/or MouseEvents:
@hsolter
Scroll by wheel just works fine, even ifinteractiveis false. Interactive only concerns the flick action ofFlickable. Have you tried?Yup I've tried it at the original code .With your modification it does not work anymore. if I remove the modification, scroll by wheel works as usual. Maybe scrolling by wheel means flicking in some sense?
@hsolter
Oops. My bad.
@hsolter said in ScrollView interfering with MouseArea and/or MouseEvents:Maybe scrolling by wheel means flicking in some sense?
You must be right...
When I first tried, I did it like this:
onPressed: { scrollView.contentItem.interactive = false .... } onReleased: { .... scrollView.contentItem.interactive = true }That is what I meant with "dynamically".
This preserves the wheelscroll, but then, you must take care that the
releasedevent never gets stolen or lost of course. -
@hsolter
Oops. My bad.
@hsolter said in ScrollView interfering with MouseArea and/or MouseEvents:Maybe scrolling by wheel means flicking in some sense?
You must be right...
When I first tried, I did it like this:
onPressed: { scrollView.contentItem.interactive = false .... } onReleased: { .... scrollView.contentItem.interactive = true }That is what I meant with "dynamically".
This preserves the wheelscroll, but then, you must take care that the
releasedevent never gets stolen or lost of course.@Diracsbracket Yeah I see what you mean. Unfortunately in the original code charts are dynamically created and has no notion if they are embedded with scrollView or some other control. I can do that in the scrollView itself if it support handling mouse events (I am not very well versed in QML) even then I might need the sync mouse clicks across controls .
-
Hello,
i found a small solution for the mouse wheel problem by using a timerScrollView { anchors { fill: parent } Component.onCompleted: contentItem.interactive = false background: Rectangle { id: scrollViewbackgroundRect anchors.fill: parent color: "transparent" MouseArea { anchors.fill: parent property var mytimer : new Timer(scrollViewbackgroundRect); onClicked: { console.log("background clicked"); } onWheel: { console.log("enabling interactive") scrollViewTours.contentItem.interactive = true mytimer.interval = 500; mytimer.repeat = false; mytimer.triggered.connect(function () { console.log("disabling interactive") scrollViewTours.contentItem.interactive = false }) mytimer.start(); } } } }the JS function
function Timer(parent) { return Qt.createQmlObject("import QtQuick 2.0; Timer {}", parent); }