0

How to get the look of curved Scroll bar/scroll view as shown below in QML with Label or TextArea?

Curved Scroll View

Basically this application is not a touch application. Environment, Qt 5.7.0 in Linux.

Prady
  • 663
  • 3
  • 11
  • 28

2 Answers2

3

You can use PathInterpolator from Controls.2. The example below is some Slider modification, you can adopt it for your needs:

import QtQuick 2.9
import QtQuick.Controls 2.2

ApplicationWindow {
    id: mainWindow
    visible: true
    width: 400
    height: 400

    Path {
        id: myPath
        startX: 0; startY: 20

        PathCurve { x: 100; y: 40 }
        PathCurve { x: 200; y: 10 }
        PathCurve { x: 300; y: 40 }
    }

    Slider {
        id: control
        width: 300
        height: 50
        anchors.centerIn: parent
        background: Rectangle {
            anchors.fill: parent
            color: "orange"
            Canvas {
                 anchors.fill: parent
                 contextType: "2d"
                 onPaint: {
                     context.strokeStyle = "MediumPurple";
                     context.path = myPath;
                     context.stroke();
                 }
             }
            PathInterpolator {
                id: motionPath
                path: myPath
                progress: control.visualPosition
            }
        }
        handle: Rectangle {
            width: 30
            height: 30
            radius: 15
            color: "DodgerBlue"
            x: motionPath.x - 15
            y: motionPath.y - 15
        }
    }
}
folibis
  • 12,048
  • 6
  • 54
  • 97
1

You can use a Flickable to have your view. To this Flickable you attatch a ScrollBar which you can style.

To style this ScrollBar is a bit tricky, for some of its properties are bullshit.

The position-property, which is documented as

This property holds the position of the scroll bar, scaled to 0.0 - 1.0.

will never reach 1.0 unless, the handles size is 0. You don't really have the ability to set the size of the handle, though. It will be automatically resized. So if you don't want to have a handle that fills the width of the ScrollBar entirely, you need to use a Item as a base and add a the visual inside this, so you have the sovereignity again.

All together, it might look like this:

Flickable {
    anchors.fill: parent

    contentWidth: width
    contentHeight: mainWindow.height * 10

    Rectangle {
        width: 640
        height: mainWindow.height * 10
        gradient: Gradient {
            GradientStop { color: 'orchid'; position: 0 }
            GradientStop { color: 'orange'; position: 1 }
        }
    }

    ScrollBar.vertical: ScrollBar {
        id: scrollBar
        width: 50
        contentItem: Item {
            // This will deal with the bullshit of the position. Imperfect, as I do not consider any margins/paddings
            property real normalizedPosition: scrollBar.position * (scrollBar.height  / (scrollBar.height - height))
            Rectangle {
                // Draw the curve by defining a function for x in dependance of the position.
                x: Math.sin(Math.PI * parent.normalizedPosition) * 40 
                width: 10
                height: parent.height // I use the default height, so it 
                                      // really goes from top to bottom.
                                      // A smaller height means, you should 
                                      // also alter the y value to have a 
                                      // more natural behavior.
                radius: 5
                color: 'green'
                Text {
                    text: parent.parent.normalizedPosition
                }
            }
        }
    }
}