如何将 QML Slider 的 mouseArea 限制为仅手柄?
How to restrict the mouseArea of a QML Slider to the handle only?
我想使用 QtQuick.Controls 实现 Slider
,其中只有 handle
是可点击的并且可以用来拖动 handle
。如果您单击 groove
,则不会发生任何事情,handle
应该保留在原处。如何将 Slider
的 mouseArea
限制为仅 handle
?
在下面的例子中 Slider
是整体可点击的 Slider
width
和 height
:
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
模板,但我真的不知道该怎么做。
我所有的搜索努力都一无所获。任何帮助将不胜感激。
我可能是错的,但我认为这违背了所有桌面平台上滑块的行为,出于可用性原因需要考虑这一点。除此之外,让我们试试:
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
, 在 滑块本身之上。这些中的每一个都将填充手柄两侧的可用 space,有效地窃取凹槽会为这些区域接收的所有鼠标事件。
我想使用 QtQuick.Controls 实现 Slider
,其中只有 handle
是可点击的并且可以用来拖动 handle
。如果您单击 groove
,则不会发生任何事情,handle
应该保留在原处。如何将 Slider
的 mouseArea
限制为仅 handle
?
在下面的例子中 Slider
是整体可点击的 Slider
width
和 height
:
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
模板,但我真的不知道该怎么做。
我所有的搜索努力都一无所获。任何帮助将不胜感激。
我可能是错的,但我认为这违背了所有桌面平台上滑块的行为,出于可用性原因需要考虑这一点。除此之外,让我们试试:
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
, 在 滑块本身之上。这些中的每一个都将填充手柄两侧的可用 space,有效地窃取凹槽会为这些区域接收的所有鼠标事件。