QML自定义实现ScrollBar

栾英资
2023-12-01

Qt自带的ScrollBar滚动条或多或少有点问题(测试时候,有的时候点击拖着不好用;放大缩小时候滚动条也不好用)

简单实现了一个


/*
    必须设置属性
    property var target
    property var lengthvalue  //记录外面大的区域的大小 和target不同 Point(x,y) x:width, y:height
*/

import QtQuick 2.9

Rectangle
{
    id: scrollBar
    property var target
    property var lengthvalue  //记录外面大的区域的大小 和target不同 Point(x,y) x:width, y:height

    property var orientation: Qt.Vertical  //竖直
    property var ispress: false
    property var m_step: 1;  //变化比例

    signal poschange(var mouseX,var mouseY)


    width: orientation==Qt.Vertical ? 10: target.width
    height: orientation==Qt.Vertical ? target.height : 10
    anchors.right: orientation==Qt.Vertical ? target.right : undefined
    anchors.left: orientation==Qt.Vertical ?  undefined : target.left

    radius: 5
    z : target.z+1
    color: "#80c0c0c0"
    opacity: 0.01

    Rectangle {
        id : crect;
        color: "black"
        radius: 5
        z : scrollBar.z+1
        property bool mishow: false

        //位置
        width: orientation==Qt.Vertical ? 10: 50
        height: orientation==Qt.Vertical ? 50 : 10

        MouseArea {
            anchors.fill: parent
            propagateComposedEvents: true

            property var p_old


            drag.filterChildren: true
            drag.target: crect

            drag.axis: orientation==Qt.Vertical ?  Drag.YAxis : Drag.XAxis

            drag.minimumX: orientation==Qt.Vertical ? 0 : 0
            drag.maximumX: orientation==Qt.Vertical ? 0 : Math.ceil(scrollBar.width - crect.width)

            drag.minimumY: orientation==Qt.Vertical ? 0 : 0
            drag.maximumY: orientation==Qt.Vertical ? Math.ceil(scrollBar.height - crect.height) : 0


            onMouseXChanged: {
                if (!scrollBar.ispress) return;
                if (scrollBar.orientation==Qt.Vertical) return;

                var offset_x = crect.x;
                scrollBar.poschange(-offset_x*scrollBar.m_step,0);

            }
            onMouseYChanged: {

                if (!scrollBar.ispress) return;
                if (scrollBar.orientation!=Qt.Vertical) return;

                var offset_y = Math.ceil(crect.y);
                scrollBar.poschange(0,-offset_y*scrollBar.m_step);

            }

            //鼠标按住
            onPressed: {
                if (crect.mishow)
                {
                    scrollBar.ispress = true;
                }
                else
                    scrollBar.ispress = false;
                p_old = Qt.point(crect.x,crect.y);
            }
            onReleased: {
                scrollBar.ispress = false;
            }
        }
    }

    //鼠标事件
    MouseArea
    {
        anchors.fill: parent
        hoverEnabled: true

        //鼠标进入进出实现显示和不显示
        onEntered: {
            if (crect.mishow)
                scrollBar.opacity=0.8;
        }
        onExited: {
            if (!scrollBar.ispress)
                scrollBar.opacity=0.01;
        }
        
    }

    Component.onCompleted: {
        //加载完成是设置长度
        if (orientation==Qt.Vertical)
        {
            var hs = scrollBar.height*scrollBar.height/lengthvalue.y;
            crect.height = Math.floor(hs);
            m_step = (lengthvalue.y)/scrollBar.height;
            if (scrollBar.height<lengthvalue.y) crect.mishow = true;
        }
        else
        {
            var hs = scrollBar.width*scrollBar.width/lengthvalue.x;
            crect.width =  Math.floor(hs);
            m_step = (lengthvalue.x)/scrollBar.width;
            if (scrollBar.width<lengthvalue.x) crect.mishow = true;

        }
    }
}

使用代码

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Rectangle{
        id : crect;
        y :100
        x : 100
        //anchors.centerIn: parent
        width: 600; height: 300;
        //color: "#00000000"
        border.color: "green"
        //z:1
        clip: true

        Rectangle{
            x : 0; y : -10
            width: 10;height: 10
            color: "red"
        }
        Rectangle{
            x : 600; y : -10
            width: 10;height: 10
            color: "red"
        }
        Rectangle{
            x : -10; y : 300
            width: 10;height: 10
            color: "red"
        }

        ScrollBarDrag{
            target: crect;
            lengthvalue  : Qt.point(imags.width,imags.height)
            orientation: Qt.Vertical
            onPoschange:{
                m_translate.x = mouseX;
                m_translate.y = mouseY;
            }
        }
        ScrollBarDrag{
            target: crect;
            lengthvalue  : Qt.point(imags.width,imags.height)
            orientation: Qt.Horizontal
            onPoschange:{
                m_translate.x = mouseX;
                m_translate.y = mouseY;
            }
        }

        Image {
            id: imags
            source: "qrc:/bg.png"
            //anchors.fill: parent
            //width: 300;height: 300
            //width: 100; height: 600;
            fillMode : Image.TileHorizontally

            transform: [
                        Translate {id: m_translate },
                        Scale {id: m_scale }
                    ]
        }

    }
}

 

 

 类似资料: