首页 文章

如何将QML Slider的mouseArea仅限制为句柄?

提问于
浏览
0

我想使用QtQuick.Controls实现 Slider ,其中只有 handle 是可点击的,可以用来拖动 handle . 如果单击 groove ,则不会发生任何事情, handle 应该保持原样 . 如何仅将 SlidermouseArea 限制为 handle

在下面的示例中, Slider 可以在整个 Slider widthheight 上单击:

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

Window {
    id: mainItem
    width: 800
    height: 400
    visible: true

    Slider{
        id: autoSlider
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        maximumValue: 1.0
        value: 0
        updateValueWhileDragging : false

        style: SliderStyle {
            groove: Rectangle {
                implicitWidth: 350
                implicitHeight: 8
                color: "gray"
                radius: 8
            }
            handle: Rectangle {
                anchors.centerIn: parent
                color: control.pressed ? "white" : "lightgray"
                border.color: "gray"
                border.width: 2
                implicitWidth: 45
                implicitHeight: 45
                radius: 12
            }
        }
    }
}

我考虑过更改"..\qml\QtQuick\Controls"文件夹中的 Slider.qml 模板,但我无法弄清楚要做什么 .

我所有的搜索努力都没有结果 . 任何帮助将不胜感激 .

1 回答

  • 1

    我可能错了,但我认为这违背了所有桌面平台上滑块的行为,出于可用性的原因需要考虑这一点 . 除此之外,让我们试试:

    diff --git a/src/controls/Slider.qml b/src/controls/Slider.qml
    index 20d1102..da6f051 100644
    --- a/src/controls/Slider.qml
    +++ b/src/controls/Slider.qml
    @@ -258,7 +258,7 @@ Control {
             }
    
             onPositionChanged: {
    -            if (pressed)
    +            if (pressed && handleHovered)
                     updateHandlePosition(mouse, preventStealing)
    

    当手柄没有悬停时,我们不希望手柄位置发生变化,因为这意味着鼠标位于手柄之外 .

    var point = mouseArea.mapToItem(fakeHandle, mouse.x, mouse.y)
    @@ -272,18 +272,21 @@ Control {
                 if (handleHovered) {
                     var point = mouseArea.mapToItem(fakeHandle, mouse.x, mouse.y)
                     clickOffset = __horizontal ? fakeHandle.width/2 - point.x : fakeHandle.height/2 - point.y
    +
    +                pressX = mouse.x
    +                pressY = mouse.y
    +                updateHandlePosition(mouse, !Settings.hasTouchScreen)
                 }
    -            pressX = mouse.x
    -            pressY = mouse.y
    -            updateHandlePosition(mouse, !Settings.hasTouchScreen)
             }
    

    接下来,在 onPressed 句柄的 if (handleHovered) 条件内移动手柄位置更新 .

    onReleased: {
    -            updateHandlePosition(mouse, Settings.hasTouchScreen)
    -            // If we don't update while dragging, this is the only
    -            // moment that the range is updated.
    -            if (!slider.updateValueWhileDragging)
    -                range.position = __horizontal ? fakeHandle.x : fakeHandle.y;
    +            if (handleHovered) {
    +                updateHandlePosition(mouse, Settings.hasTouchScreen)
    +                // If we don't update while dragging, this is the only
    +                // moment that the range is updated.
    +                if (!slider.updateValueWhileDragging)
    +                    range.position = __horizontal ? fakeHandle.x : fakeHandle.y;
    +            }
                 clickOffset = 0
                 preventStealing = false
             }
    

    最后,对 onReleased 处理程序进行类似的更改 .

    这会让你得到你想要的东西,尽管边缘有点粗糙 - 字面意思 . 我认为这种互动不是100%,而是尝试一下 . 通过更多的实验,你应该能够让它完美地运作 .

    另一个hacky选项是修改 Slider.qml 以在滑块本身上方的句柄的任一侧 MouseArea . 这些中的每一个都将填充手柄两侧的可用空间,有效地窃取凹槽将为这些区域接收的所有鼠标事件 .

相关问题