You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在QML中绘制带可变同心层的环形扇形靶标?

实现可调节同心层数的靶标扇形图形

需求说明

  • 绘制类似靶标的图形,由12个扇形分割的同心圆组成
  • 同心层数支持通过SpinBox在2-10范围内调整
  • 整体尺寸固定,各层间距计算公式:外圆半径 ÷ 层数
  • 保留原Repeater循环单个扇形组件的结构,在单个扇形内绘制多条弧实现同心层

修改后的完整代码

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts
import QtQuick.Controls

Window {
    width: 600
    height: 600
    visible: true
    id: window

    property int sectors: 12
    property int concentricLayers: 5 // 默认5层,范围2-10

    Rectangle {
        anchors.centerIn: parent
        width: 600
        height: 600
        Repeater {
            model: sectors
            CircleSector {
                anchors.fill: parent
                anchors.margins: 10
                sectors: window.sectors
                sector: index
                concentricLayers: window.concentricLayers
                highlightSector: spinBoxSector.value
            }
        }
    }

    RowLayout {
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        spacing: 20
        Frame {
            SpinBox {
                id: spinBoxSector
                Layout.fillWidth: true
                from: 0
                to: sectors - 1
                value: 1
                wrap: true
                stepSize: 1
                label.text: "选中扇形"
            }
        }
        Frame {
            SpinBox {
                id: spinBoxLayers
                Layout.fillWidth: true
                from: 2
                to: 10
                value: window.concentricLayers
                stepSize: 1
                label.text: "同心层数"
                onValueChanged: window.concentricLayers = value
            }
        }
    }
}

CircleSector.qml

import QtQuick 2.12
import QtQuick.Shapes 1.12

Shape {
    id: circleSector
    antialiasing: true

    property int sectors: 12
    property int sector: 0
    property int concentricLayers: 5
    property int highlightSector: 0

    property real fromAngle: sector * (360 / sectors)
    property real toAngle: (sector + 1) * (360 / sectors)
    property real centerX: width / 2
    property real centerY: height / 2
    // 外层半径(减去margins后的实际半径)
    property real outerRadius: centerX - anchors.margins

    Repeater {
        model: concentricLayers
        ShapePath {
            id: layerPath
            // 计算当前层的内外半径:第index层(从0开始)的内层半径是outerRadius - (index+1)*layerSpacing
            property real layerSpacing: outerRadius / concentricLayers
            property real innerRadius: outerRadius - (index + 1) * layerSpacing
            property real currentOuterRadius: outerRadius - index * layerSpacing

            // 根据扇形是否选中、层数奇偶设置填充色
            fillColor: (sector == highlightSector) ? 
                        (index % 2 == 0 ? "#ff9933" : "#ffcc80") : 
                        (index % 2 == 0 ? "#f0f8ff" : "#e6f2ff")
            strokeColor: "grey"
            strokeWidth: 1

            startX: centerX; startY: centerY
            // 绘制到内层弧的起始点
            PathLine { 
                x: centerX + innerRadius * Math.cos(fromAngle * Math.PI / 180)
                y: centerY + innerRadius * Math.sin(fromAngle * Math.PI / 180)
            }
            // 内层弧
            PathArc {
                radiusX: innerRadius; radiusY: innerRadius
                x: centerX + innerRadius * Math.cos(toAngle * Math.PI / 180)
                y: centerY + innerRadius * Math.sin(toAngle * Math.PI / 180)
                useLargeArc: false
                sweepDirection: PathArc.Clockwise
            }
            // 绘制到外层弧的结束点
            PathLine { 
                x: centerX + currentOuterRadius * Math.cos(toAngle * Math.PI / 180)
                y: centerY + currentOuterRadius * Math.sin(toAngle * Math.PI / 180)
            }
            // 外层弧
            PathArc {
                radiusX: currentOuterRadius; radiusY: currentOuterRadius
                x: centerX + currentOuterRadius * Math.cos(fromAngle * Math.PI / 180)
                y: centerY + currentOuterRadius * Math.sin(fromAngle * Math.PI / 180)
                useLargeArc: false
                sweepDirection: PathArc.Counterclockwise
            }
            // 回到中心闭合路径
            PathLine { x: centerX; y: centerY }
        }
    }
}

关键改动说明

  1. 新增层数控制:在main.qml中添加了控制同心层数的SpinBox,绑定到window.concentricLayers属性,限制范围2-10
  2. 扇形内多层弧实现:在CircleSector中用Repeater循环生成对应层数的ShapePath,每层对应一个环形扇形段
  3. 半径计算:根据外层半径和层数计算每层间距layerSpacing = outerRadius / concentricLayers,再计算每层的内外半径,确保各层间距均匀
  4. 颜色逻辑:选中的扇形使用橙色系交替色,未选中的使用浅蓝系交替色,区分层次和选中状态
  5. 路径闭合:每层ShapePath通过"中心→内层起始点→内层弧→外层结束点→外层弧→中心"的路径,绘制闭合的环形扇形

内容的提问来源于stack exchange,提问作者ephemera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 12:20:36