I'm trying to implement a widget similar to the default ScrollView widget, except the scrollbars are always visible and are much thicker + easier to see. There doesn't seem to be an easy way to actually theme or adjust the styling of the scrollbars on ScrollView to get what I want, so I've ended up trying to hack Flickable to do this.
However, overriding the scrollbars in Flickable like this has one downside: It turns out that it either makes the scrollbars overlap in the bottom right corner, OR the vertical one stretches all the way down, and the horizontal one fits in the remaining space. What should happen instead is that there should be a tiny square left over in the corner where neither scrollbar should go.
Using the anchors.bottom / anchors.right lines, I can get that corner to behave as expected. But at the expense of the top/left sides of the scrollbars now being out of view.
I can "solve" this start-of-scrollbars-out-of-view issue by assigning the top/left anchors (i.e. commented lines) to the corresponding flickable boundaries. However, while it looks ok, it results in a stream of QML ScrollBar: Possible anchor loop detected on vertical anchor. warnings flooding the console. Is there any way to avoid this anchor loop error, or should I just look to ignore/filter those warnings?
The code ("ScrollPane.qml"):
/// ScrollPane - Custom ScrollView-like widget based on Flickable,
/// with additional functionality for getting the theming we want.
import QtQuick 2.3
import QtQuick.Controls 2.3
// The region that displays the contents
Flickable {
id: flickable
clip: true
boundsBehavior: Flickable.StopAtBounds
//boundsMovement: Flickable.StopAtBounds
// Increase scrolling speed, as Flickable is too sluggish
// Note: Windows default is 2500
//maximumFlickVelocity : 10000 // XXX: overshoots
maximumFlickVelocity : 7000
// Component.onCompleted: {
// console.log("scroll view rate = %1".arg(maximumFlickVelocity))
// }
// Scrollbars ===========================
// Scrollbar Parameters -----------------
// Width/Thickness of Gutter (px)
property int gutterSize : 18
// Width/Thickness of Scroll Thumb (px)
property int thumbSize : gutterSize - 3
// Gutter Color
property color gutterColor: "#FFFFFF"
property color gutterBorderColor: Qt.rgba(0, 0, 0, 0.9)
// Scroll Thumb Colors
property color thumbColor: "#BBBBBB"
property color thumbPressedColor: "#777777"
property color thumbBorderColor: "#CCCCCC"
// Vertical Scrollbar: Always On --------
ScrollBar.vertical: ScrollBar {
id: verticalScrollbar
policy: ScrollBar.AlwaysOn
/// NOTE: This is needed to keep the bottom-right corner empty. But, is buggy due to the Anchor Loop warning
//anchors.top: flickable.top // FIXME: Enable to show rounded top; Disabled due to Anchor Loop warning
anchors.bottom: horizontalScrollbar.top
// Gutter/Trough
background: Rectangle {
implicitWidth: flickable.gutterSize
border {
color: flickable.gutterBorderColor
width: 1.5
}
color: flickable.gutterColor
opacity: 0.2
}
// Scroll Thumb
contentItem: Rectangle {
implicitWidth: flickable.thumbSize
radius: width / 2
border {
color: flickable.thumbBorderColor
width: 1
}
color: parent.pressed ? flickable.thumbPressedColor
: flickable.thumbColor
opacity: 0.9
}
}
// Horizontal Scrollbar: As Needed --------
ScrollBar.horizontal: ScrollBar {
id: horizontalScrollbar
policy: ScrollBar.AsNeeded
/// NOTE: This is needed to keep the bottom-right corner empty. But, is buggy due to the Anchor Loop warning
//anchors.left: flickable.left // FIXME: Enable to show rounded LHS; Disabled due to Anchor Loop warning
anchors.right: verticalScrollbar.left
// Gutter/Trough
background: Rectangle {
implicitHeight: flickable.gutterSize
border {
color: flickable.gutterBorderColor
width: 1.5
}
color: flickable.gutterColor
opacity: 0.2
}
// Scroll Thumb
contentItem: Rectangle {
implicitHeight: flickable.thumbSize
radius: height / 2
border {
color: flickable.thumbBorderColor
width: 1
}
color: parent.pressed ? flickable.thumbPressedColor
: flickable.thumbColor
opacity: 0.9
}
}
}