首页 > 解决方案 > QML ListView 调整大小自定义小部件委托

问题描述

我有以下问题:

我有一个 ListView,里面有这样的电影: 在此处输入图像描述

我想现在我会点击一部电影,以便与其他人一起变得更大并且独立地高,但出于某种原因,我得到了这个。

在此处输入图像描述

我已经将宽度尺寸增加了很多只是为了显示我的问题,实际上,它不需要那么大。

你能向我解释为什么它保持那个按钮的形状,即使那些缩放是正确的,除了实际的形状?


这是我使用自定义小部件的方式(它是 ListView 的委托):

SideButtons {
    id: imageButton
    property int recDynamicHeight: listViewID.height/10 * 5
    property int recOriginalHeight: listViewID.height/10 * 5
    property int recDynamiclWidth: listViewID.width/10 * 1.2
    property int recOriginalWidth: listViewID.width/10 * 1.2
    roundedCorners: ['TL','TR']
    clickable: false
    radius: 20
    width: recDynamiclWidth
    height: recDynamicHeight
    backgroundImage: model.imgUrl
    Text {
        property bool isVisible: false
        color: "#ffffff"
        anchors.fill: parent
        visible: textid.isVisible
        id: textid
        text: model.title
        font.bold: true
        horizontalAlignment: Text.AlignLeft
        font.pixelSize: listViewID.width/8/9
        topPadding: listViewID.width/8/9
        leftPadding: listViewID.width/8/9
    }
    Text {
        anchors.topMargin: listViewID.width/8/9
        color: "#ffffff"
        anchors.fill: parent
        visible: textid.isVisible
        id: yearId
        text: model.year
        horizontalAlignment: Text.AlignLeft
        font.pixelSize: listViewID.width/8/9
        topPadding: listViewID.width/8/9*2
        leftPadding: listViewID.width/8/9
    }
    onRelease: {
        console.log("release")
        imageButton.recDynamicHeight = imageButton.recOriginalHeight;
        imageButton.recDynamiclWidth = imageButton.recOriginalWidth;
        textid.isVisible = false;
        textid.visible = textid.isVisible;
    }
    onPressed: {
        console.log("pressed")
        imageButton.recDynamicHeight = imageButton.recOriginalHeight;
        imageButton.recDynamicHeight += imageButton.recDynamicHeight * 10/100;
        imageButton.recDynamiclWidth += 400;
        textid.isVisible = true;
        textid.visible = textid.isVisible;
    }
    onClicked: {
        load_page(PageType.movie_detailed_view, model.title, model.description, model.imgUrl, model.type, model.year)
    }
}

这是 SideButton 的实际代码:

Item {
    id: sideButtonID

    property var coordinates: generateButtonShapeCoordinates(width, height)

    property bool hasRoundedCorners: true
    property var roundedCorners: ['TL','TR','BR','BL']
    property var backgroundImage: ""
    property var clickable: true

    property int radius: 10

    property alias mouseX: mouseArea.mouseX
    property alias mouseY: mouseArea.mouseY
    readonly property bool pressedOnArea: containsMouse && mouseArea.pressed
    onPressedOnAreaChanged: canvasID.requestPaint()

    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 icon: ""

    property var colorPressed: "green"
    property var colorSelected: "#434343"
    property var colorUnselected: "#434343"

    signal clicked
    signal release
    signal pressed

    function noRoundedCornersShapeCoordinates(width, height){
        var topLeft = Qt.point(topLeftOffset.x, topLeftOffset.y)
        var topRight = Qt.point(width - topRightOffset.x, topRightOffset.y)
        var bottomRight = Qt.point(width - bottomRightOffset.x, height - bottomRightOffset.y)
        var bottomLeft = Qt.point(bottomLeftOffset.x, height - bottomLeftOffset.y)

        return {
            topLeft : topLeft,
            topRight : topRight,
            bottomRight : bottomRight,
            bottomLeft : bottomLeft
        };
    }
    function roundedCornersShapeCoordinates(width, height){
        var offset = radius
        var topLeftOr = Qt.point(topLeftOffset.x, topLeftOffset.y)
        var topLeftDown = Qt.point(topLeftOffset.x, topLeftOffset.y +offset)
        var topLeftRight = Qt.point(topLeftOffset.x + offset, topLeftOffset.y)

        var topRightOr = Qt.point(width - topRightOffset.x, topRightOffset.y)
        var topRightLeft = Qt.point(width - topRightOffset.x - offset, topRightOffset.y)
        var topRightDown = Qt.point(width - topRightOffset.x, topRightOffset.y + offset)

        var bottomRightOr = Qt.point(width - bottomRightOffset.x, height - bottomRightOffset.y)
        var bottomRightTop = Qt.point(width - bottomRightOffset.x, height - bottomRightOffset.y -offset)
        var bottomRightLeft = Qt.point(width - bottomRightOffset.x - offset, height - bottomRightOffset.y)

        var bottomLeftOr = Qt.point(bottomLeftOffset.x, height - bottomLeftOffset.y)
        var bottomLeftDown = Qt.point(bottomLeftOffset.x + offset, height - bottomLeftOffset.y)
        var bottomLeftLeft = Qt.point(bottomLeftOffset.x, height - bottomLeftOffset.y -offset)

        return {
            topLeftDown : topLeftDown,
            topLeftOr : topLeftOr,
            topLeftRight : topLeftRight,

            topRightLeft : topRightLeft,
            topRightOr : topRightOr,
            topRightDown : topRightDown,

            bottomRightTop : bottomRightTop,
            bottomRightOr : bottomRightOr,
            bottomRightLeft : bottomRightLeft,

            bottomLeftDown : bottomLeftDown,
            bottomLeftOr : bottomLeftOr,
            bottomLeftLeft : bottomLeftLeft,
        };
    }

    function generateButtonShapeCoordinates(width, height){
        if(hasRoundedCorners){
            return roundedCornersShapeCoordinates(width, height)
        }
        else{
            return noRoundedCornersShapeCoordinates(width, height)
        }
    }

    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 corners = coordinates

        var polygon =[[]]

        for (const [key, value] of Object.entries(corners)) {
            polygon.push([corners[key].x,corners[key].y])
        }

        var point = [mouseX, mouseY]
        return inside(point, polygon)
    }

    MouseArea {
        id: mouseArea
        propagateComposedEvents: true
        anchors.fill: parent
        hoverEnabled: true
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        onClicked: {
            if (sideButtonID.containsMouse){
                sideButtonID.clicked();
            }
            else{
                mouse.accepted = false;
                return;
            }
        }
        onReleased : sideButtonID.release();
        onPressed: {
            if (sideButtonID.containsMouse){
                sideButtonID.pressed();
            }
            else{
                mouse.accepted = false;
                return;
            }
        }
    }
    Shape {
        id: shapeRootID
        antialiasing: true
        vendorExtensionsEnabled: true
        asynchronous: true
        anchors.fill: parent

        Canvas {
            id: canvasID
            anchors.fill: parent
            onImageLoaded: requestPaint()
            onPaint: {
                var ctx = getContext("2d");

                if(clickable)
                    ctx.fillStyle = pressedOnArea ? colorPressed : (containsMouse ? colorSelected : colorUnselected)

                ctx.lineWidth = 2;
                ctx.beginPath();

                var corners = coordinates
                var firstTime = true

                if(!hasRoundedCorners){
                    ctx.moveTo(corners['topLeft'].x,corners['topLeft'].y)
                    ctx.lineTo(corners['topRight'].x,corners['topRight'].y)
                    ctx.lineTo(corners['bottomRight'].x,corners['bottomRight'].y)
                    ctx.lineTo(corners['bottomLeft'].x,corners['bottomLeft'].y)
                }
                else{
                    //https://www.w3schools.com/tags/canvas_arcto.asp

                    var radius = sideButtonID.radius

                    if(roundedCorners.includes('TL')){
                        ctx.moveTo(corners['topLeftDown'].x,corners['topLeftDown'].y);
                        ctx.arcTo(corners['topLeftOr'].x,corners['topLeftOr'].y,
                                  corners['topLeftRight'].x+radius, corners['topLeftRight'].y,
                                  radius)
                    }
                    else{
                        ctx.moveTo(corners['topLeftOr'].x,corners['topLeftOr'].y);
                    }

                    if(roundedCorners.includes('TR')){
                        ctx.lineTo(corners['topRightLeft'].x, corners['topRightLeft'].y);
                        ctx.arcTo(corners['topRightOr'].x,corners['topRightOr'].y,
                                  corners['topRightDown'].x, corners['topRightDown'].y+radius,
                                  radius)
                    }
                    else{
                        ctx.lineTo(corners['topRightOr'].x, corners['topRightOr'].y);
                    }


                    if(roundedCorners.includes('BR')){
                        ctx.lineTo(corners['bottomRightTop'].x, corners['bottomRightTop'].y);
                        ctx.arcTo(corners['bottomRightOr'].x,corners['bottomRightOr'].y,
                                  corners['bottomRightLeft'].x - radius, corners['bottomRightLeft'].y,
                                  radius)
                    }
                    else{
                        ctx.lineTo(corners['bottomRightOr'].x, corners['bottomRightOr'].y)
                    }

                    if(roundedCorners.includes('BL')){
                        ctx.lineTo(corners['bottomLeftDown'].x, corners['bottomLeftDown'].y);
                        ctx.arcTo(corners['bottomLeftOr'].x,corners['bottomLeftOr'].y,
                                  corners['bottomLeftLeft'].x, corners['bottomLeftLeft'].y - radius,
                                  radius)
                    }
                    else{
                        ctx.lineTo(corners['bottomLeftOr'].x, corners['bottomLeftOr'].y)
                    }
                }
                ctx.fill()

                if(backgroundImage != ""){
                    ctx.clip()
                    ctx.drawImage(backgroundImage,0,0, parent.width, parent.height);
                }
            }
        }
    }

    Image {
        x: 0
        y: 0
        anchors.right: parent.right
        anchors.rightMargin: 3
        anchors.left: parent.left
        anchors.leftMargin: 6
        clip: true
        anchors.verticalCenterOffset: 0
        anchors.verticalCenter: mouseArea.verticalCenter
        fillMode: Image.PreserveAspectFit
        source: sideButtonID.icon
    }
}

你们中的任何人我做错了什么,如果是这样,我该如何解决?我已经花了这么多时间,但我没有得到问题,因为据我所知,所有的分辨率都是在那个按钮内设置的。

标签: qtqmlqqmlcomponent

解决方案


推荐阅读