has anyone ever bent a (QML) RangeSlider?
-
@mzimmers
well, there is Dial:
https://doc.qt.io/qt-5/qml-qtquick-controls2-dial.htmlwhich is probably close to what you want, but not for 2 ranges
the marketplace has this one:
https://marketplace.qt.io/products/circularslider
which is free and you can probably adjust it for your case, since source code is available ?
-
@J-Hilk I'm familiar with the marketplace app CircularSlider, and actually do use it for a different purpose in my app. It's a great product, but it's somewhat limited in its customization potential, so I don't think that adding a 2nd handle is a trivial undertaking.
I've experimented with overlaying 2 CircularSliders, but the issue there is how to give control to both handles.
@Mesrine I'll take another look at the customization options, though I don't know how the handles will track movement along a curved background. And, I may eventually take you up on your offer, though for now I'd like to continue exploring all options for this.
-
So, I'm back to looking at this. I'm trying to customize RangeSlider for this. Here's the progress:
- I have the circular background I want
- I have the circular progrss bar I want
- I have the handle I want, and it's properly positioned
What's not working is, I can't grab my custom handle and move it. There is a "grab" area within the circle that is invisible, but moves my handle. I need to figure out whether I can change that "grab" area to be the location of my custom handle.
Here's my code. Sorry it's not shorter, but at least it's a complete reproducible example. Any suggestions would be appreciated. Thanks...
import QtQuick import QtQuick.Controls import QtQuick.Shapes Window { id: mainWindow readonly property double sliderStartAngle: 30.0 readonly property double sliderEndAngle: 330.0 readonly property double sliderAngleRange: sliderEndAngle - sliderStartAngle readonly property double sliderRotation: 90.0 readonly property double minTemp: 11 readonly property double maxTemp: 400 readonly property int sliderHeight: 200 readonly property int sliderWidth: 200 readonly property int sliderStepSize: 10 // because temps are deciDegrees readonly property int sliderTrackWidth: 20 readonly property int internalRadius: (sliderWidth - sliderTrackWidth) / 2 property int handleOffset: 0 property double heatSetpointValue: minTemp property double chillSetpointValue: minTemp + ((maxTemp - minTemp) / 4) width: 800 height: 480 visible: true Shape { id: sliderBg anchors.centerIn: parent width: sliderWidth height: sliderHeight layer.enabled: true layer.samples: 8 ShapePath { strokeColor: 'lightblue' fillColor: 'transparent' strokeWidth: sliderTrackWidth capStyle: ShapePath.RoundCap PathAngleArc { radiusX: internalRadius radiusY: internalRadius centerX: sliderWidth / 2 centerY: sliderHeight / 2 startAngle: sliderStartAngle sweepAngle: sliderAngleRange } } } RangeSlider { id: rangeSlider anchors.centerIn: parent height: sliderHeight width: sliderWidth rotation: sliderRotation from: minTemp to: maxTemp first.value: heatSetpointValue second.value: chillSetpointValue background: Shape { id: chillProgress property double chillProgressRatio: 1.0 - ((maxTemp - rangeSlider.second.value) / (maxTemp - minTemp)) property double chillProgressAngle: chillProgressRatio * (sliderAngleRange) * (-1) anchors.centerIn: parent width: sliderWidth height: sliderHeight layer.enabled: true layer.samples: 8 rotation: sliderRotation * (-1) ShapePath { strokeColor: 'blue'//therm.isRunning ? Colors.userBlue500 : Colors.ngaTransparent fillColor: 'transparent'//Colors.ngaTransparent strokeWidth: sliderTrackWidth capStyle: ShapePath.RoundCap PathAngleArc { id: pathAngleArc radiusX: internalRadius radiusY: internalRadius centerX: sliderWidth / 2 centerY: sliderHeight / 2 startAngle: sliderStartAngle * (-1) sweepAngle: chillProgress.chillProgressAngle } } } second.handle: Rectangle { id: chillHandle height: sliderTrackWidth width: height radius: height / 2 color: 'red' x: rangeSlider.width / 2 - width / 2 y: rangeSlider.height / 2 - height / 2 z: 2 antialiasing: true transform: [ Translate { y: -(sliderHeight / 2) + (sliderTrackWidth / 2) + handleOffset }, Rotation { id: rotation angle: chillProgress.chillProgressAngle + (sliderStartAngle * (-1)) origin.x: chillHandle.width / 2 origin.y: chillHandle.height / 2 } ] MouseArea { anchors.fill: parent onClicked: console.log("clicked!") } } } }
-
If you want a
RangeSlider
that is more than half a circle you need to create a custom control using a mouse area... .- if the control is
horizontal
one needs to know they
value where the user clicked. This is needed to map thevisualPosition
to ax,y
properties of the handle. - I do not know a way to get the
mouse.y
where the user clicked from insideRangeSlider
type, I suggest creating a custom control. - need to account for https://doc.qt.io/qt-6.2/qml-qtquick-controls2-control.html#event-handling
If the
RangeSlider
is just half of a Circle then I think you can map thevisualPosition
to anx,y
value and you can just customize thebackground
and thehandles
of theRangeSlider
.The price is increasing :).
- if the control is