Custom ScrollBar to add top & bottom buttons (Windows Style)
-
I have a QT application and need to custom my ListView ScrollBar, to have a Windows Look&Fell scroll, including top and bottom buttons (to scroll up or down when clicked)
As far as I know, all I can customize from ScrollBar is the contentItem and the background. There is no default way to add these top & bottom buttons. To add it manually
To add buttons at top & bottom I have added margins in the contentItem, so I have space for my buttons. But with that margin, the height of the contentItem is smaller and with a lot of elements in my ListView the handle is NOT visible...
Is it possible to have a minimum height for the contentItem? Is there any other way to have this 2 buttons?
Thanks in advance
Code:
import QtQuick 2.7 import QtQuick.Controls 2.0 Item { anchors.fill: parent MouseArea { anchors.fill: id_list onWheel: id_list.flick(0, wheel.angleDelta.y * 5) } ListModel { id: listModel Component.onCompleted: { for (var i = 0; i < 1000; i++) append({ role_text: "Item " + i}); } } ListView { id: id_list anchors.fill: parent interactive: false boundsBehavior: Flickable.StopAtBounds focus: true Keys.onPressed: { if (event.key === Qt.Key_Up) id_list.flick(0, 500) else if (event.key === Qt.Key_Down) id_list.flick(0, -500) } keyNavigationEnabled: true model: listModel ScrollBar.vertical: ScrollBar { id: id_scroll interactive: true; policy: ScrollBar.AlwaysOn anchors { top: parent.top; topMargin: 0; bottom: parent.bottom; bottomMargin: 0; right: parent.right/*; rightMargin: -2*/} contentItem: Item { implicitWidth: 11 implicitHeight: 100 Rectangle { anchors { top: parent.top; topMargin: 13; bottom: parent.bottom; bottomMargin: 13; left: parent.left; leftMargin: -2; right: parent.right; rightMargin: -2} color: "green" } } background: Item { implicitWidth: 11 implicitHeight: id_scroll.height Rectangle { anchors { top: parent.top; bottom: parent.bottom; bottomMargin: 0; left: parent.left; right: parent.right} color: "#ededed" } Rectangle { anchors { top: parent.top; right: parent.right } height: 15; width: height color: "red" MouseArea { anchors.fill: parent onClicked: id_list.flick(0, 500) } } Rectangle { anchors { bottom: parent.bottom; right: parent.right } height: 15; width: height color: "red" MouseArea { anchors.fill: parent onClicked: id_list.flick(0, -500) } } } } delegate: Rectangle { height: 40 width: id_list.width color: "white" border { color: "black"; width: 1 } TextEdit { anchors.centerIn: parent id: id_text text: role_text; selectByMouse: true; readOnly: true; persistentSelection: true } } } }
-
You can use
Control::topPadding
andbottomPadding
to reserve space:import QtQuick 2.9 import QtQuick.Controls 2.0 ApplicationWindow { id: window width: 400 height: 400 visible: true ListView { id: listView model: 100 anchors.fill: parent ScrollBar.vertical: ScrollBar { id: vbar topPadding: 16 + 2 bottomPadding: 16 + 2 Rectangle { width: parent.width height: 16 color: upButton.pressed ? "blue" : "red" opacity: vbar.contentItem.opacity MouseArea { id: upButton anchors.fill: parent SmoothedAnimation { target: listView property: "contentY" running: upButton.pressed velocity: 1000 to: 0 } onReleased: { if (!listView.atYBeginning) listView.flick(0, 1000) } } } Rectangle { y: parent.height - height width: parent.width height: 16 color: downButton.pressed ? "blue" : "red" opacity: vbar.contentItem.opacity MouseArea { id: downButton anchors.fill: parent SmoothedAnimation { target: listView property: "contentY" running: downButton.pressed to: listView.contentHeight - listView.height velocity: 1000 } onReleased: { if (!listView.atYEnd) listView.flick(0, -1000) } } } } delegate: ItemDelegate { text: modelData width: parent.width } } }
-
You can use
Control::topPadding
andbottomPadding
to reserve space:import QtQuick 2.9 import QtQuick.Controls 2.0 ApplicationWindow { id: window width: 400 height: 400 visible: true ListView { id: listView model: 100 anchors.fill: parent ScrollBar.vertical: ScrollBar { id: vbar topPadding: 16 + 2 bottomPadding: 16 + 2 Rectangle { width: parent.width height: 16 color: upButton.pressed ? "blue" : "red" opacity: vbar.contentItem.opacity MouseArea { id: upButton anchors.fill: parent SmoothedAnimation { target: listView property: "contentY" running: upButton.pressed velocity: 1000 to: 0 } onReleased: { if (!listView.atYBeginning) listView.flick(0, 1000) } } } Rectangle { y: parent.height - height width: parent.width height: 16 color: downButton.pressed ? "blue" : "red" opacity: vbar.contentItem.opacity MouseArea { id: downButton anchors.fill: parent SmoothedAnimation { target: listView property: "contentY" running: downButton.pressed to: listView.contentHeight - listView.height velocity: 1000 } onReleased: { if (!listView.atYEnd) listView.flick(0, -1000) } } } } delegate: ItemDelegate { text: modelData width: parent.width } } }
@jpnurmi Thanks for your help!!
Now I have to face the 2nd problem, the handle height. If you add 1000 elements to the list, the scrollbar contentItem is not visible, due to the dinamic size... How can I set a minimum height for the scroll handle?
-
ScrollBar::minimumSize
has been added in Qt Quick Controls 2.4 (Qt 5.11). The first beta was just released if you want to try it out: http://blog.qt.io/blog/2018/03/01/qt-5-11-beta-released/ -
ScrollBar::minimumSize
has been added in Qt Quick Controls 2.4 (Qt 5.11). The first beta was just released if you want to try it out: http://blog.qt.io/blog/2018/03/01/qt-5-11-beta-released/@jpnurmi Thanks. I am working with Qt 5.9.4 libraries (compiled from source) and can not update right now to 5.11. Is there anything I can do with this Qt version?