1

I use a ListView and inside each Item of this ListView, I have a ComboBox or a SpinBox.

My problem is that when I want to scroll my ListView, if my mouse goes on a ComboBox or a SpinBox, the focus will change and the scroll will now be on this Item instead of the list.

I would like that focus is set on these Item only if I click on them.

Code example:

import QtQuick.Controls 1.4

ListView {
    id: list
    ScrollBar.vertical: ScrollBar {}
    ...
    model: DelegateModel {
        id:delegate
        model: myModel
        delegate : Rectangle {
             id: rect
             ...
             SpinBox {
                 id: spin 
                 ...
             }
        }     
    }
}

How could I proceed ?

Ed Nio
  • 593
  • 2
  • 11
  • 27

1 Answers1

1

This is a common problem with the old QtQuick.Controls 1.x components, that they greedily grab the mouse events. To my knowledge, there is no official way to prevent this.

Here you find a solution, on how to overlay a such a component (in this case a Slider) with a MouseArea that prevents that misbehaviour.

Alternatively you might switch to the new QtQuick.Controls 2.x-Spinbox. As this has a different default look, you might need to adjust it, to look (more) similar to the old one. Here you can find a description on how you can do this.

Remember that it is easy to have both: QtQuick.Controls 1.x and QtQuick.Controls 2.x in one file, by importing them with aliases.

Digging into the source of the QtQuick.Controls 1.4 we can find also a hacky solution.

Relevant Files:

We can see, a SpinBox is a Control. The SpinBox has a child MouseArea, which handles the onWheel-event. We're gonna disable this MouseArea. To access it, we need to know the index in the SpinBox.children. We see in Control that there are two Loader as children (Index 0 and 1). In SpinBox we have two other children before the MouseArea (Index 2 and 3) -> So we need to set idOfSpinBox.children[4].enabled = false to disable the wheel-sensitivity.

import QtQuick 2.7
import QtQuick.Controls 1.4

ApplicationWindow {
    id: root
    visible: true
    width: 800
    height: 600

    ListView {
        model: 20
        width: 100
        height: 200
        delegate: SpinBox {
            Component.onCompleted: children[4].enabled = false
        }
    }
}

or if we want to have the scroll wheel enabled, when the SpinBox was clicked, we use:

delegate: SpinBox {
    id: spinBox
    Component.onCompleted: children[4].enabled = Qt.binding(function() { return spinBox.activeFocus } )
}

But then we need to find some way to lose this focus again.

Community
  • 1
  • 1
  • Thanks for your complete answer. I tried both examples and they works fine. However, at this time I need to use `QtQuick.Controls 1.x` because the `QML` part will be a part of a "classic" `QWidget` application and I need that some components have a "classic" look. It might change in the futur. – Ed Nio May 17 '17 at 09:41
  • Added some other way, by inspecting the source of the `SpinBox` - I hope it helps. – derM - not here for BOT dreams May 17 '17 at 10:08
  • Hello, thanks for digging into the sources, it works for SpinBox and it is a great solution. However, I tried to apply this solution for `ComboBox` but if you disable `MouseArea` ( `children[2]` ) , you will also disable `onClicked` so the ComboBox won't work work anymore – Ed Nio May 17 '17 at 11:13