Как реализовать изогнутый вид прокрутки в qml?

Как получить вид изогнутой полосы прокрутки/прокрутки, как показано ниже, в QML с меткой или TextArea?

Вид с изогнутой прокруткой

В основном это приложение не является сенсорным приложением. Среда, Qt 5.7.0 в Linux.


person Prady    schedule 17.07.2017    source источник


Ответы (2)


Вы можете использовать PathInterpolator из Controls.2. В приведенном ниже примере представлена ​​некоторая Slider модификация, вы можете адаптировать ее для своих нужд:

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
        }
    }
}
person folibis    schedule 17.07.2017
comment
хе-хе, я сделал ту же ошибку, глядя на изображение, решив, что это слайдер, а не ScrollBar. Хорошее решение для слайдера! - person derM; 17.07.2017
comment
Это довольно креативно. :) Обратите внимание, что PathInterpolator относится к Qt Quick, а не к Qt Quick Controls 2. - person Mitch; 17.07.2017

Вы можете использовать Flickable для просмотра. К этому Flickable вы прикрепляете ScrollBar, который вы можете стилизовать.

Стилизовать этот ScrollBar немного сложно, потому что некоторые его свойства — полная ерунда.

Свойство position, которое задокументировано как

Это свойство содержит положение полосы прокрутки в масштабе от 0,0 до 1,0.

никогда не достигнет 1.0, если только размер дескриптора не равен 0. Однако у вас нет возможности установить размер дескриптора. Он будет автоматически изменен в размере. Поэтому, если вы не хотите иметь дескриптор, который полностью заполняет ширину ScrollBar, вам нужно использовать Item в качестве основы и добавить внутри него визуал, чтобы у вас снова был суверенитет.

Все вместе это может выглядеть так:

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
                }
            }
        }
    }
}
person derM    schedule 17.07.2017