如何知道旋转项的边界矩形

时间:2014-10-18 18:15:07

标签: qt qml qt5 qtquick2

说,我有一个Flickable,里面有一个Image。我需要相应地更新contentWidthcontentHeight。虽然可以手动进行适当的计算,但我想知道是否有办法获得Image(以及任何其他Item)的边界矩形?

编辑(响应Mitch's suggestion):

乍一看,它看起来很棒。我甚至开始认为我在尝试使用Item.childrenRect属性组时错过了一些东西......不幸的是,修改了提供的示例以便在子项目周围绘制边界,我再次说服了自己childrenRect的属性不尊重项目的轮换。见下文:

import QtQuick 2.3
import QtQuick.Controls 1.2

Item {
    width: 400
    height: 400

    Component.onCompleted: addChildItem()

    function addChildItem() {
        var rect = Qt.createQmlObject("import QtQuick 2.3; Rectangle {}", container);
        rect.x = Math.random() * 200;
        rect.y = Math.random() * 200;
        rect.width = 64 * slider.value;
        rect.height = 64 * slider.value;
        rect.color = "green";
        rect.opacity = 0.5;
        rect.rotation = Math.random() * 360;
    }

    Row {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom

        Slider {
            id: slider
            value: 0.5

            Text {
                text: "Child item size"
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.bottom: parent.top
            }
        }

        Button {
            text: "Add child item"
            onClicked: addChildItem()
        }
    }

    Item {
        id: container
        x: 50
        y: 50
    }

    Item {
        x: container.x
        y: container.y
        Rectangle {
            x: container.childrenRect.x
            y: container.childrenRect.y
            width: container.childrenRect.width
            height: container.childrenRect.height
            color: "transparent"
            border.color: "black"
        }
    }
}

2 个答案:

答案 0 :(得分:0)

childrenRect应该考虑到轮换的边界矩形,但是有一个错误:childrenRect doesn't take transformations into account.


原始回答:

使用childrenRect

import QtQuick 2.3
import QtQuick.Controls 1.2

Item {
    width: 400
    height: 400

    Component.onCompleted: addChildItem()

    function addChildItem() {
        var rect = Qt.createQmlObject("import QtQuick 2.3; Rectangle {}", container);
        rect.x = Math.random() * 100;
        rect.y = Math.random() * 100;
        rect.width = 64 * slider.value;
        rect.height = 64 * slider.value;
        rect.color = "green";
        rect.opacity = 0.5;
        rect.rotation = Math.random() * 360;
    }

    Row {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom

        Slider {
            id: slider
            value: 0.5

            Text {
                text: "Child item size"
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.bottom: parent.top
            }
        }

        Button {
            text: "Add child item"
            onClicked: addChildItem()
        }
    }

    Item {
        id: container
        anchors.centerIn: parent
    }

    Text {
        text: "Total rotated bounds"

        Rectangle {
            id: boundsRect
            width: container.childrenRect.width
            height: container.childrenRect.height
            anchors.top: parent.bottom
            color: "transparent"
            border.color: "black"
        }
    }
}

example screenshot

答案 1 :(得分:0)

边界矩形可以通过自定义函数计算。以下是QML代码,它确实做了并说明了这一点。下面的代码仅考虑轮换,但是可以进行调整以考虑翻译和缩放比例。知道单个转换项的边界矩形后,就可以遍历多个项的边界矩形并计算总体边界矩形。

import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Window 2.11

Window {
    width: 640
    height: 480
    visible: true

    function rotatePoint(point, pivotPoint, degrees) {
        var radians = degrees * (Math.PI / 180)
        var sinAngle = Math.sin(radians)
        var cosAngle = Math.cos(radians)

        var pointX = point.x
        var pointY = point.y

        var pivotPointX = pivotPoint.x
        var pivotPointY = pivotPoint.y

        pointX -= pivotPointX
        pointY -= pivotPointY

        var rotatedPointX = (pointX * cosAngle - pointY * sinAngle) + pivotPointX
        var rotatedPointY = (pointX * sinAngle + pointY * cosAngle) + pivotPointY

        return Qt.point(rotatedPointX, rotatedPointY)
    }

    function calculateBoundingRect(rect, degrees) {
        var x = rect.x
        var y = rect.y
        var width = rect.width
        var height = rect.height

        var centerPoint = Qt.point(x + width / 2, y + height / 2)

        var topLeftPoint = Qt.point(x, y)
        var topRightPoint = Qt.point(x + width, y)
        var bottomRightPoint = Qt.point(x + width, y + height)
        var bottomLeftPoint = Qt.point(x, y + height)

        var rotatedTopLeftPoint = rotatePoint(topLeftPoint, centerPoint, degrees)
        var rotatedTopRightPoint = rotatePoint(topRightPoint, centerPoint, degrees)
        var rotatedBottomRightPoint = rotatePoint(bottomRightPoint, centerPoint, degrees)
        var rotatedBottomLeftPoint = rotatePoint(bottomLeftPoint, centerPoint, degrees)

        var rotatedPointsXValues = [rotatedTopLeftPoint.x, rotatedTopRightPoint.x, rotatedBottomRightPoint.x, rotatedBottomLeftPoint.x]
        var rotatedPointsYValues = [rotatedTopLeftPoint.y, rotatedTopRightPoint.y, rotatedBottomRightPoint.y, rotatedBottomLeftPoint.y]

        var rotatedPointsMinX = Math.min.apply(null, rotatedPointsXValues)
        var rotatedPointsMaxX = Math.max.apply(null, rotatedPointsXValues)
        var rotatedPointsMinY = Math.min.apply(null, rotatedPointsYValues)
        var rotatedPointsMaxY = Math.max.apply(null, rotatedPointsYValues)

        var boundingRectTopLeftPoint = Qt.point(rotatedPointsMinX, rotatedPointsMinY)
        var boundingRectTopRightPoint = Qt.point(rotatedPointsMaxX, rotatedPointsMinY)
        var boundingRectBottomLeftPoint = Qt.point(rotatedPointsMinX, rotatedPointsMaxY)

        return Qt.rect(
                    boundingRectTopLeftPoint.x, boundingRectTopLeftPoint.y,
                    boundingRectTopRightPoint.x - boundingRectTopLeftPoint.x,
                    boundingRectBottomLeftPoint.y - boundingRectTopLeftPoint.y)
    }

    Rectangle {
        id: rectangle1
        width: 100
        height: 200
        gradient: Gradient {
            GradientStop {
                position: 0
                color: "#1ce327"
            }

            GradientStop {
                position: 1
                color: "#0e65ec"
            }
        }
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        antialiasing: true
        rotation: slider.value

        property rect boundingRect: calculateBoundingRect(Qt.rect(x, y, width, height), rotation)
    }

    Rectangle {
        id: rectangle
        width: rectangle1.boundingRect.width
        height: rectangle1.boundingRect.height
        color: "#00000000"
        antialiasing: true
        border.width: 1
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
    }

    Slider {
        id: slider
        antialiasing: true

        anchors.right: parent.right
        anchors.rightMargin: 10
        anchors.left: parent.left
        anchors.leftMargin: 10
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 10

        from: -720
        to: 720
        value: 0
    }
}

enter image description here

相关问题