[英]A way to draw a concentric circles' sector in QML?
I need to draw something like a target, a bunch of concentric circles split into 12 or so sectors (pizza slices).我需要画一些像目标一样的东西,一堆同心圆分成 12 个左右的扇区(披萨片)。 So the number of "layers" inside the outer circle can change anywhere from 2 to 10, the size of the whole target should remain the same, and the distance between inner circles should be equal (bascially OuterCircleRadius / NumberOfLayers)所以外圈内的“层”数可以在 2 到 10 之间变化,整个目标的大小应该保持不变,内圈之间的距离应该相等(基本上是 OuterCircleRadius / NumberOfLayers)
So far I came up with a code that basically draws a single segment of a circle, then, by putting a Repeater in the main file I get a full circle, split into 12 sectors, which is what I need.到目前为止,我想出了一个基本上绘制圆的单个部分的代码,然后通过在主文件中放置一个 Repeater,我得到一个完整的圆,分成 12 个扇区,这就是我需要的。 Now I need to find a way to add a number of concentric circles inside the outer one.现在我需要找到一种方法来在外圈内添加多个同心圆。 The problem is that the number of concentric circles is not constant, and is set by user.问题是同心圆的数量不是恒定的,是由用户设置的。 So the "target" should change when a different number of layers is chosen (for example with a SpinBox). So the "target" should change when a different number of layers is chosen (for example with a SpinBox). So far my idea is to draw a few additional arcs inside of a single sector so I can keep the Repeater.到目前为止,我的想法是在单个扇区内绘制一些额外的弧线,这样我就可以保留 Repeater。 My code below.我的代码如下。
// 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
Rectangle {
anchors.centerIn: parent
width: 600
height: 600
Repeater {
model: sectors
CircleSector {
anchors.fill: parent
anchors.margins: 10
sectors: window.sectors
sector: index
fillColor: index == spinBox.value ? "orange" : "aliceblue"
}
}
}
Frame {
SpinBox {
id: spinBox
Layout.fillWidth: true
from: 0
to: sectors - 1
value: 1
wrap: true
stepSize: 1
}
}
}
// 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 real from: sector * (360 / sectors)
property real to: (sector + 1) * (360 / sectors)
property real centerX: width / 2
property real centerY: height / 2
property alias fillColor: shapePath.fillColor
property alias strokeColor: shapePath.strokeColor
property real fromX: centerX + centerX * Math.cos(from * Math.PI / 180)
property real fromY: centerY + centerY * Math.sin(from * Math.PI / 180)
property real toX: centerX + centerX * Math.cos(to * Math.PI / 180)
property real toY: centerY + centerY * Math.sin(to * Math.PI / 180)
containsMode: Shape.FillContains
ShapePath{
id: shapePath
fillColor: "aliceblue"
strokeColor: "grey"
startX: centerX; startY: centerY
PathLine { x: fromX; y: fromY }
PathArc{
radiusX: centerX; radiusY: centerY
x: toX; y: toY
}
PathLine{ x: centerX; y: centerY }
}
}
Depending on what you want to do with your polar coordinate system you could use PolarChartView .根据您要对极坐标系执行的操作,您可以使用PolarChartView 。 With that you can also easily plot data on it.有了它,您还可以轻松地获取 plot 数据。
import QtQuick
import QtQuick.Controls
import QtCharts
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
PolarChartView {
anchors.fill: parent
legend.visible: false
antialiasing: true
ValueAxis {
id: axisAngular
min: 0
max: 1
labelsVisible: false
lineVisible: false
tickCount: axisAngularSpinBox.value
}
ValueAxis {
id: axisRadial
min: 0
max: 1
labelsVisible: false
lineVisible: false
tickCount: axisRadialSpinBox.value
}
SplineSeries {
id: series
axisAngular: axisAngular
axisRadial: axisRadial
pointsVisible: true
}
}
Column {
SpinBox {
id: axisAngularSpinBox
value: 9
}
SpinBox {
id: axisRadialSpinBox
value: 10
}
}
}
You could use this Canvas
solution.您可以使用此Canvas
解决方案。 It isn't pretty, but it hopefully does what you want.它不漂亮,但它希望做你想要的。
import QtQuick
import QtQuick.Controls
ApplicationWindow {
id: root
title: "Polar Coordinates Canvas"
width: 640
height: 480
visible: true
color: "white"
property int numCircles: circlesSpinBox.value
property int numSegments: segmentsSpinBox.value
Canvas {
id: canvas
anchors.centerIn: parent
width: 400
height: canvas.width
onPaint: {
var ctx = getContext("2d")
ctx.fillStyle = 'white'
ctx.fillRect(0, 0, canvas.width, canvas.height);
const centerX = canvas.width / 2
const centerY = canvas.height / 2
const radius = canvas.width / 2
const circleDistance = (canvas.width / 2) / root.numCircles
for (let i = 1; i <= root.numCircles; ++i) {
let r = i * circleDistance
ctx.beginPath()
ctx.arc(centerX, centerY, r, 0, 2 * Math.PI, false)
ctx.lineWidth = 1
ctx.strokeStyle = 'black'
ctx.stroke()
}
if (root.numSegments < 2)
return
const segmentAngle = 360 / root.numSegments
if (root.numSegments % 2 === 0) { // even
for (let s = 0; s < (root.numSegments / 2); ++s) {
let a = s * segmentAngle
ctx.beginPath()
let x = centerX + radius * Math.cos(a * (Math.PI / 180))
let y = centerY + radius * Math.sin(a * (Math.PI / 180))
ctx.moveTo(x, y)
x = centerX + radius * Math.cos((a + 180) * (Math.PI / 180))
y = centerY + radius * Math.sin((a + 180) * (Math.PI / 180))
ctx.lineTo(x, y)
ctx.lineWidth = 1
ctx.strokeStyle = 'black'
ctx.stroke()
}
} else { // odd
for (let s = 0; s < root.numSegments; ++s) {
let a = s * segmentAngle
ctx.beginPath()
let x = centerX + radius * Math.cos(a * (Math.PI / 180))
let y = centerY + radius * Math.sin(a * (Math.PI / 180))
ctx.moveTo(x, y)
ctx.lineTo(centerX, centerY)
ctx.lineWidth = 1
ctx.strokeStyle = 'black'
ctx.stroke()
}
}
}
}
Column {
SpinBox {
id: circlesSpinBox
value: 3
onValueChanged: canvas.requestPaint()
}
SpinBox {
id: segmentsSpinBox
value: 7
onValueChanged: canvas.requestPaint()
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.