Home > database >  Why is spacing creating more than expected?
Why is spacing creating more than expected?

Time:10-17

I recognized in my example a small gap between the repeated objects about one pixel more or less. Depending on the property int size this gap might change position. I also tested with property double size but this seem not changing the effect.

// FILE main.qml
import QtQuick 2.11
import QtQuick.Controls 2.4

Rectangle {
  width: 640
  height: 320

  BarrierTape {}
}
// File BarrierTape.qml
import QtQuick 2.11
import QtQuick.Layouts 1.11

Item {
  id: barrierTape
  property int size: 100
  x:200
  y:100
  ColumnLayout {
    spacing: barrierTape.size * Math.sin(Math.PI/3)
    Repeater {
      model: 2
      Rectangle {
        width: barrierTape.size
        height: barrierTape.size * Math.sin(Math.PI/3)
        color: "#ffd100"
      }
    }
  }
  ColumnLayout {
    x: -barrierTape.size*3/4
    y:  barrierTape.size/2 * Math.sin(Math.PI/3)
    spacing: barrierTape.size * Math.sin(Math.PI/3)
    Repeater {
      model: 2
      Rectangle {
        width: barrierTape.size
        height: barrierTape.size * Math.sin(Math.PI/3)
       color: "#ffd100"
      }
    }
  }
  ColumnLayout {
    x:  barrierTape.size*3/4
    y: -barrierTape.size/2 * Math.sin(Math.PI/3)
    spacing: barrierTape.size * Math.sin(Math.PI/3)
    Repeater {
      model: 2
      Rectangle {
        width: barrierTape.size
        height: barrierTape.size * Math.sin(Math.PI/3)
        color: "#ffd100"
      }
    }
  }
  ColumnLayout {
    spacing: barrierTape.size * Math.sin(Math.PI/3)
    y:  barrierTape.size * Math.sin(Math.PI/3)
    Repeater {
      model: 2
      Rectangle {
        width: barrierTape.size
        height: barrierTape.size * Math.sin(Math.PI/3)
        color: "#222222"
      }
    }
  }
  ColumnLayout {
    x: -barrierTape.size * 3/4
    y:  barrierTape.size * 3/2 * Math.sin(Math.PI/3)
    spacing: barrierTape.size* Math.sin(Math.PI/3)
    Repeater {
      model: 2
      Rectangle {
        width: barrierTape.size
        height: barrierTape.size * Math.sin(Math.PI/3)
        color: "#222222"
      }
    }
  }
  ColumnLayout {
    x:  barrierTape.size * 3/4
    y:  barrierTape.size * 1/2 * Math.sin(Math.PI/3)
    spacing: barrierTape.size* Math.sin(Math.PI/3)
    Repeater {
      model: 2
      Rectangle {
        width: barrierTape.size
        height: barrierTape.size * Math.sin(Math.PI/3)
        color: "#222222"
      }
    }
  }
}

Further the code have a lot of Boilerplate and I don't know how to achieve the same behavior with less. I thought that creating first an item with all six rectangles and than repeating them would help, but if I put Repeater in one ColumnLayout seems to ignoring the x and y values. I struggle to refactor this file.

EDIT 1:

This is a sample of what it kind of should look like:

enter image description here

CodePudding user response:

This uses a slightly complicated Hexagon component which I did a while ago.

main.qml

import QtQuick

Window {
    id: root
    width: 640
    height: 640
    visible: true
    title: qsTr("Hello World")
    color: "#444444"

    property color color1: "#ffd100"
    property color color2: "#222222"

    property int hexRadius: 50
    property real hexInnerRadius: (Math.sqrt(3) / 2) * root.hexRadius
    property int spacing: 2

    component BarrierTape : Column {
        spacing: root.spacing
        Repeater {
            model: 4
            Item {
                width: root.hexRadius * 1.5
                height: 2 * root.hexInnerRadius

                Hexagon {
                    anchors.centerIn: parent
                    width: 2 * root.hexRadius
                    height: 2 * root.hexRadius
                    radius: 10
                    fillColor: (index % 2 == 0) ? root.color1 : root.color2
                    antialiasing: true
                }
            }
        }
    }

    Row {
        x: 100
        y: 150
        spacing: root.spacing
        Repeater {
            model: 4

            BarrierTape {
                y: index * -root.hexInnerRadius
            }
        }
    }
}

Hexagon.qml

import QtQuick
import QtQuick.Shapes

Shape {
    id: root
    width: 200
    height: 200

    property int radius: 10
    property alias fillColor: path.fillColor

    layer.enabled: root.antialiasing
    layer.smooth: root.antialiasing
    layer.samples: root.antialiasing ? 4 : 0

    ShapePath {
        id: path
        joinStyle: ShapePath.MiterJoin
        strokeWidth: 0
        strokeColor: "transparent"
        startX: 0
        startY: 0
    }

    onRadiusChanged: {
        // Only construct polygon if radius changed from 0 to 1 or vice versa.
        if ((root.radius   root.__previousRadius) === 1)
            root.constructPolygon()

        root.__previousRadius = root.radius
    }
    Component.onCompleted: root.constructPolygon()

    property real __centerX: root.width / 2
    property real __centerY: root.height / 2
    property real __radius: Math.min(root.width, root.height) / 2

    property int __previousRadius: root.radius

    property int minRadius: 0
    property int maxRadius: root.__radius * Math.cos(root.toRadians(180.0 / 6))

    property int __actualRadius: Math.max(root.minRadius, Math.min(root.maxRadius, root.radius))

    function constructPolygon() {
        root.clearPathElements()

        if (root.radius === 0)
            root.constructNonRoundedPolygonPath()
        else
            root.constructRoundedPolygonPath()
    }

    function toRadians(degrees) {
        return degrees * (Math.PI / 180.0)
    }

    function constructNonRoundedPolygonPath() {
        for (var cornerNumber = 0; cornerNumber < 6; cornerNumber  ) {
            let angleToCorner = root.toRadians(cornerNumber * (360.0 / 6))

            if (cornerNumber === 0) {
                path.startX = Qt.binding(function() {
                    return root.__centerX   root.__radius * Math.cos(0)
                })
                path.startY = Qt.binding(function() {
                    return root.__centerY   root.__radius * Math.sin(0)
                })
            } else {
                let pathLine = Qt.createQmlObject('import QtQuick 2.15; PathLine {}', path)
                pathLine.x = Qt.binding(function() {
                    return root.__centerX   root.__radius * Math.cos(angleToCorner)
                })
                pathLine.y = Qt.binding(function() {
                    return root.__centerY   root.__radius * Math.sin(angleToCorner)
                })
                path.pathElements.push(pathLine)
            }
        }

        // Close the polygon
        var pathLineClose = Qt.createQmlObject('import QtQuick 2.15; PathLine {}', path)
        pathLineClose.x = Qt.binding(function() { return path.startX } )
        pathLineClose.y = Qt.binding(function() { return path.startY } )
        path.pathElements.push(pathLineClose)
    }

    property real __halfInteriorCornerAngle: 90 - (180.0 / 6)
    property real __halfCornerArcSweepAngle: 90 - root.__halfInteriorCornerAngle
    property real __distanceToCornerArcCenter: root.__radius - root.__actualRadius /
                                               Math.sin(root.toRadians(root.__halfInteriorCornerAngle))

    function constructRoundedPolygonPath() {
        for (var cornerNumber = 0; cornerNumber < 6; cornerNumber  ) {
            let angleToCorner = cornerNumber * (360.0 / 6)

            let pathArc = Qt.createQmlObject('import QtQuick 2.15; PathArc {
                                                property real centerX;
                                                property real centerY }', path)
            pathArc.centerX = Qt.binding(function() {
                return root.__centerX   root.__distanceToCornerArcCenter
                        * Math.cos(root.toRadians(angleToCorner))
            })
            pathArc.centerY = Qt.binding(function() {
                return root.__centerY   root.__distanceToCornerArcCenter
                        * Math.sin(root.toRadians(angleToCorner))
            })
            pathArc.x = Qt.binding(function() {
                return pathArc.centerX   root.__actualRadius
                        * (Math.cos(root.toRadians(angleToCorner   root.__halfCornerArcSweepAngle)))
            })
            pathArc.y = Qt.binding(function() {
                return pathArc.centerY   root.__actualRadius
                        * (Math.sin(root.toRadians(angleToCorner   root.__halfCornerArcSweepAngle)))
            })
            pathArc.radiusX = Qt.binding(function() { return root.__actualRadius })
            pathArc.radiusY = Qt.binding(function() { return root.__actualRadius })

            if (cornerNumber === 0) {
                path.startX = Qt.binding(function() {
                    return pathArc.centerX   root.__actualRadius
                            * (Math.cos(root.toRadians(angleToCorner - root.__halfCornerArcSweepAngle)))
                })
                path.startY = Qt.binding(function() {
                    return pathArc.centerY   root.__actualRadius
                            * (Math.sin(root.toRadians(angleToCorner - root.__halfCornerArcSweepAngle)))
                })
            } else {
                let pathLine = Qt.createQmlObject('import QtQuick 2.15; PathLine {}', path)
                pathLine.x = Qt.binding(function() {
                    return pathArc.centerX   root.__actualRadius
                            * (Math.cos(root.toRadians(angleToCorner - root.__halfCornerArcSweepAngle)))
                })
                pathLine.y = Qt.binding(function() {
                    return pathArc.centerY   root.__actualRadius
                            * (Math.sin(root.toRadians(angleToCorner - root.__halfCornerArcSweepAngle)))
                })
                path.pathElements.push(pathLine)
            }

            path.pathElements.push(pathArc)
        }

        // Close the polygon
        var pathLineClose = Qt.createQmlObject('import QtQuick 2.15; PathLine {}', path)
        pathLineClose.x = Qt.binding(function() { return path.startX} )
        pathLineClose.y = Qt.binding(function() { return path.startY} )
        path.pathElements.push(pathLineClose)
    }

    function clearPathElements() {
        for (var i = 0; i !== path.pathElements.length;   i)
            path.pathElements[i].destroy()

        path.pathElements = []
    }
}

enter image description here

CodePudding user response:

I have been having great success at using SVG and a Button hack for rendering SVGs in different colors:

import QtQuick 2.15
import QtQuick.Controls 2.15

Page {
    background: Rectangle { color: "#444444" }

    Hex { x: 87.5; y: 150; color: "#ffd100" }
    Hex { x: 175; y: 100; color: "#ffd100" }
    Hex { x: 262.5; y: 50; color: "#ffd100" }

    Hex { x: 87.5; y: 450; color: "#222222" }
    Hex { x: 175; y: 400; color: "#222222" }
    Hex { x: 262.5; y: 350; color: "#222222" }

    Hex { x: 87.5; y: 350; color: "#ffd100" }
    Hex { x: 175; y: 300; color: "#ffd100" }
    Hex { x: 262.5; y: 250; color: "#ffd100" }

    Hex { x: 87.5; y: 250; color: "#222222" }
    Hex { x: 175; y: 200; color: "#222222" }
    Hex { x: 262.5; y: 150; color: "#222222" }
}

//Hex.qml
import QtQuick 2.15
import QtQuick.Controls 2.15

Item {
    property alias color: btn.icon.color
    Item {
        anchors.centerIn: parent
        width: 200
        height: 200
        Button {
            id: btn
            background: Item { }
            icon.color: "#ffd100"
            icon.height: parent.height
            icon.width: parent.width
            icon.source: "Hex.svg"
        }
    }
}

//Hex.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-200 -200 400 400">
<path stroke="black" stroke-width="25" stroke-linejoin="round" d="M 100 0 L 50 86.6 L -50 86.6 L -100 0 L -50 -86.6 L 50 -86.6 z" />
</svg>

You can enter image description here

  • Related