QMLカスタム実装ScrolBar

5322 ワード

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

コードの使用
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 }
                    ]
        }

    }
}