✤ Apr 30, 2016 ✤
嗯,其实在qt里有滚轮的控件,叫 ScrollBar ,在 Qt.labs.controls 1.0 包里,好吧,我就是闲的慌,想自己实现一个它的效果。=。=说起来汗颜的是,一开始看 Documentation 的时候,看到这个控件的几个属性,还各种的满不在乎,觉得尼玛这个设计好愚蠢。但当我实现了这个控件时,才发现,尼玛,我自己竟然也把这几个属性留出接口了,这真是,好尴尬啊……打脸啊……
分析下它的功能吧,仔细把玩了下竖向滚轮。
其实,从描述上可以看到,如果就是简单的拿 Rectangle 堆出一个滚轮的话,它是一个三层结构。
一开始我的第一反应是在中间的滑块上单独再有一个 MouseArea ,不过后来仔细琢磨了下发现其实那样设计会造成移动滑块的时候的处理变得更加复杂,其实那样设计除了看着舒心,并没有带来什么好处。所以,权衡之后,还是打算只用一个大 MouseArea 盖在上面,通过对鼠标坐标移动的信号来对不同的事件进行处理。
其实想通的话,整个滚轮实现起来并不难。不过有两个坑的地方,一个是按空白的地方,页面自动跑那里,我是靠了一个定时器来实现的页面滚动,通过定时页面高度自增自减。还一个地方其实就是滚轮移动比例到页面移动比例的换算千万别弄忘了,(。・`ω´・) 我一开始就忘记了,结果整个页面起飞了。
嗯,剩下这个控件很简单了,我依然将控件的逻辑部分和样式进行了分离,分别在 control 和 style 里,同时 control 里为了能够控制页面滚动,所以留了一个 Item 类型的属性,如果没对这个属性进行设置,会发现滚轮没有效果,但是不会报错的!
最终的大概效果。
代码如下:
control文件
//VerticalScrollBar.qml
import QtQuick 2.5
import QtQuick.Controls 1.3
import QtQuick.Controls.Private 1.0
Control {
id: root
implicitWidth: 10
implicitHeight: parent.height
style: Qt.createComponent("VerticalScrollBarStyle.qml", root)
property Item handleItem // verticalscrollbar 控制的Flickable类控件,必须要设置哦,不设置滚轮是没有反应的
property alias size: scrollbtn.height //滚轮的长度 height
property alias position: scrollbtn.y //滚轮的高度 y
property int __scrollState: 0 //-1向上滚 0不滚 1向下滚
property int __scrollStep: 20 //按下空白时候的移动步长
property double __offset: 0
property bool __dragScroll: false //是否按下滚轮
clip: true
Timer {
interval: 20
running: !!handleItem
&&__scrollState!==0
&& handleItem.contentY>=0
&& handleItem.contentY<=handleItem.contentHeight-handleItem.height
repeat: true
onTriggered: {
if (!!handleItem) {
handleItem.contentY += __scrollStep*__scrollState
}
}
}
Loader {
id: backboard
property Component __bkract //背景图案
anchors.fill: parent
sourceComponent: __style && __style.background ? __style.background : __bkract
}
Loader {
id: scrollbtn
property Component __scrollbtn //滑轮图案
width: parent.width
sourceComponent: __style && __style.scroll ? __style.scroll : __scrollbtn
onYChanged: {
if (y<mousearea.mouseY && y>mousearea.mouseY-height) {
__scrollState = 0
}
}
}
MouseArea {
id: mousearea
anchors.fill: backboard
property double oldY: -1
onPressed: {
if(mouseY<=scrollbtn.y) {//按住滚轮空白区域滚轮往上
__scrollState = -1
}else if(mouseY>=scrollbtn.y+scrollbtn.height) {//按住滚轮空白区域滚轮往下
__scrollState = 1
}else {
__scrollState = 0
__dragScroll = true
oldY = mouseY
__offset = !!handleItem? handleItem.contentY-oldY*handleItem.contentHeight/handleItem.height : 0
}
}
onReleased: {
__scrollState = 0
__dragScroll = false
oldY = -1
}
onPositionChanged: {
if(!!handleItem && pressed && oldY!==-1) {
var offsetMouseY = mouseY*handleItem.contentHeight/handleItem.height
handleItem.contentY = __offset+offsetMouseY>=0? (__offset+offsetMouseY<=handleItem.contentHeight-handleItem.height? __offset+offsetMouseY : handleItem.contentHeight-handleItem.height) : 0
}
}
}
}
style文件
//VerticalScrollBarStyle.qml
import QtQuick 2.5
import QtQuick.Controls 1.3
import QtQuick.Controls.Private 1.0
Style {
id:style
//背景样式
property Component background: Rectangle {
color: "#fcfcfc"
Rectangle {
width: 1
height: control.height
color: "#cccccc"
}
}
//滚动条滚轮
property Component scroll: Item {
Rectangle {
width: parent.width-4
height: parent.height-4
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: 0.5
anchors.verticalCenter: parent.verticalCenter
color: control.__dragScroll? "#777777" : "#bbbbbb"
radius: width
}
}
}
嗯,就是酱紫简单就哦了,具体使用例子,请烦劳移驾github吧~[(๑→ܫ←)github传送门]