Qt QML щелкните под ограничительной рамкой - PullRequest
1 голос
/ 26 марта 2020

Я пытаюсь сделать следующее.

enter image description here

Пока единственное решение, которое я нашел, - это создать мою кнопку из C ++ и использовать setMask. Есть ли другой способ добиться того же результата, но только с помощью QML?

Моя кнопка формы:

import QtQuick 2.0
import QtQuick.Shapes 1.14



Item {
    id: sideButtonID
    property alias mouseX: mouseArea.mouseX
    property alias mouseY: mouseArea.mouseY
    readonly property bool pressed: containsMouse && mouseArea.pressed

    property point topLeftOffset: Qt.point(0, 0)
    property point topRightOffset: Qt.point(0, 0)
    property point bottomRightOffset: Qt.point(0, 0)
    property point bottomLeftOffset: Qt.point(0, 0)

    property var colorPressed: "green"
    property var colorSelected: "red"
    property var colorUnselected: "darkorange"

    signal clicked

    property var coordinate: generateButtonShapeCoordinates(x,y,width,height)
    property point topLeft: coordinate.topLeft
    property point topRight: coordinate.topRight
    property point bottomRight: coordinate.bottomRight
    property point bottomLeft: coordinate.bottomLeft


    function generateButtonShapeCoordinates(x, y, width, height){

        var topLeft = Qt.point(x-width/2 - topLeftOffset.x, y-height-topLeftOffset.y)
        var topRight = Qt.point(x+width/2-topRightOffset.x, y-height-topRightOffset.y)
        var bottomRight = Qt.point(x+width/2-bottomRightOffset.x, y-bottomRightOffset.y)
        var bottomLeft = Qt.point(x - width/2-bottomLeftOffset.x, y-bottomLeftOffset.y)

        return {
            topLeft : topLeft,
            topRight : topRight,
            bottomRight : bottomRight,
            bottomLeft : bottomLeft
        };
    }

    function inside(point, polygon) {
        // ray-casting algorithm based on
        // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
        var x = point[0], y = point[1];

        var inside = false;
        for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
            var xi = polygon[i][0], yi = polygon[i][1];
            var xj = polygon[j][0], yj = polygon[j][1];

            var intersect = ((yi > y) != (yj > y))
                    && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
            if (intersect) inside = !inside;
        }

        return inside;
    }

    property bool containsMouse: {
        var topLeft = Qt.point(0-topLeftOffset.x, 0-topLeftOffset.y)
        var topRigh = Qt.point(width-topRightOffset.x, 0-topRightOffset.y)
        var bottomRight = Qt.point(width-bottomRightOffset.x, height-bottomRightOffset.y)
        var bottomLeft = Qt.point(0-bottomLeftOffset.x, height-bottomLeftOffset.y)

        var polygon = [[topLeft.x,topLeft.y],[topRigh.x,topRigh.y],[bottomRight.x,bottomRight.y],[bottomLeft.x,bottomLeft.y]]
        var point = [mouseX, mouseY]

        return inside(point, polygon)
    }

    MouseArea {
        id: mouseArea
        anchors.fill: parent
        hoverEnabled: true
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        onClicked: if (sideButtonID.containsMouse) sideButtonID.clicked()
    }
    Shape {
        antialiasing: true
        vendorExtensionsEnabled: true
        asynchronous: true
        anchors.centerIn: parent


        ShapePath {
            id: shapepathId

            strokeWidth: -1
            fillColor: sideButtonID.pressed ? sideButtonID.colorPressed : (sideButtonID.containsMouse ? sideButtonID.colorSelected : sideButtonID.colorUnselected)
            startX: sideButtonID.topLeft.x; startY: sideButtonID.topLeft.y
            PathLine { x: sideButtonID.topRight.x; y: sideButtonID.topRight.y }
            PathLine { x: sideButtonID.bottomRight.x; y: sideButtonID.bottomRight.y }
            PathLine { x: sideButtonID.bottomLeft.x; y: sideButtonID.bottomLeft.y }
        }
        Component.onCompleted: {
            console.log("TopLeft: "+sideButtonID.topLeft)
            console.log("TopRight: "+sideButtonID.topRight)
            console.log("BottomLeft: "+sideButtonID.bottomLeft)
            console.log("BottomRight: "+sideButtonID.bottomRight)
        }
    }
}

Использование моей кнопки :

SideButtons {
    z: 100
    id: sideButtonID
    width: 130
    height: 248
    anchors.verticalCenterOffset: 9
    anchors.horizontalCenterOffset: -255
    anchors.horizontalCenter: parent.horizontalCenter
    anchors.verticalCenter: parent.verticalCenter
    bottomRightOffset: Qt.point(100,0)
    onClicked: {
        print("X: "+mouseX)
        print("Y: "+mouseY)
        print("clicked")
    }
}

Некоторые из опций, которые я слышал до сих пор, но в моем случае не годятся.

  1. с использованием изображения с прозрачным фоном ( конечно, но у меня возникнет та же проблема)
  2. создание класса C ++, который унаследует QAbstractButton (я бы предпочел избегать использования C ++ на стороне пользовательского интерфейса настолько, насколько это возможно) )
  3. использование Shape в сочетании с MouseArea (я уже делаю это, но сталкиваюсь с проблемой ограничивающего прямоугольника.

Есть ли другой способ, о котором я пока не знаю?

...