Disable mouse wheel for QML Slider

3k views Asked by At

I want to be able to scroll Flickable with mouse wheel (or two fingers on touchpad) without changing Sliders it may containt.

Sample code and result application:

import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

ApplicationWindow {
    id: rootWindow

    visible: true
    width: 400
    height: 200
    title: qsTr("Hello World")

    ScrollView {
        anchors.fill: parent
        flickableItem.flickableDirection: Flickable.VerticalFlick

        Column {
            Repeater {
                model: 40
                Slider {
                    width: rootWindow.width * 0.9
                }
            }
        }
    }
}

result application

Looks like there was some attempt to fix this in the past, but not successful.

EDIT: this relates to Controls 1.x only, as controls doesn't seem to have this issue starting from 2.0 version.

3

There are 3 answers

0
rsht On BEST ANSWER

Hack from here did it for me.

Slider {
    id: slider
    Component.onCompleted: {
        for (var i = 0; i < slider.children.length; ++i) {
            if (slider.children[i].hasOwnProperty("onVerticalWheelMoved") && slider.children[i].hasOwnProperty("onHorizontalWheelMoved")) {
                slider.children[i].destroy()
            }
        }
    }
}

This may not work with other controls (e.g. ComboBox).

2
DuKes0mE On

You can place MouseAreas on the sliders to steal the mouse wheel event.

Something like this:

import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

ApplicationWindow {
    id: rootWindow

    visible: true
    width: 400
    height: 200
    title: qsTr("Hello World")

    ScrollView {
        id: _scrollview
        anchors.fill: parent
        flickableItem.flickableDirection: Flickable.VerticalFlick

        Column {
            Repeater {
                model: 40
                Slider {
                    width: rootWindow.width * 0.9
                    property int scrollValue: 10

                    MouseArea {
                            anchors.fill: parent
                            onWheel: {
                                //check if mouse is scrolling up or down
                                if (wheel.angleDelta.y<0){
                                    //make sure not to scroll too far
                                    if (!_scrollview.flickableItem.atYEnd)
                                            _scrollview.flickableItem.contentY += scrollValue
                                }
                                else {
                                    //make sure not to scroll too far
                                    if (!_scrollview.flickableItem.atYBeginning)
                                    _scrollview.flickableItem.contentY -= scrollValue
                                }
                            }
                            onPressed: {
                                // forward mouse event
                                mouse.accepted = false
                            }
                            onReleased: {
                                // forward mouse event
                                mouse.accepted = false
                            }
                    }
                }
            }
        }
    }
}

Using the onWheel - event to forward any scrolling to the ScrollView. The other mouse events, such as clicking, can be forwarded to the parents (in this case the sliders) by setting mouse.accepted = false; for any mouse event you wish to have forwarded.

Edit: Oh, I just saw now that you don't want any changes in the sliders contents. You can also to try to place a MouseArea all over the ScrollView and do the same forwarding.

4
derM - not here for BOT dreams On

The easiest, if feasible for you, would probably be, to change from QtQuick.Controls 1.4 which can be either considered deprecated, not maintained, or low-performing to the new QtQuick.Controls 2.0

In this version your issue has been adressed.
To adress your need of QtQuick.Controls 1.4 we'll import the QtQuick.Controls 2.0 with an alias:

import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0 as NewCtrl

Column {
    Slider {
        id: oldslider // old slider from QtQuick.Controls 1.4 with your issue
        width: 500
        height: 250
    }

    NewCtrl.Slider {
        id: newsli // new slider without your issue. Both side by side
        width: 500
        height: 30
        wheelEnabled: false // use this to enable or disable the wheel
    }
}

Of course you can also alias the old controls and use the new one as the basic... Or alias both. As you like