简体   繁体   English

在 QML 中绘制弧/圆扇区?

[英]Draw an arc/circle sector in QML?

I know that it is possible to draw a circle in QML using the following code:我知道可以使用以下代码在 QML 中绘制一个圆圈:

Rectangle {
     width: 150
     height: 150
     anchors.horizontalCenter: parent.horizontalCenter
     anchors.top: parent.top
     color: "#095e7b"
     border.color: "#0a2f4a"
     border.width: 2
     radius: width*0.5
}

My question is: what if I need to draw a sector of a circle.我的问题是:如果我需要画一个圆的扇区怎么办。 (Pizza Slices) and make each of these slices clickable? (比萨切片)并使这些切片中的每一个都可点击? Can I do this using QML only?我可以只使用 QML 来做到这一点吗?

Yes, using Canvas (and Context2D ):是的,使用 Canvas(和Context2D ):

import QtQuick 2.3

Rectangle {
    width: 400
    height: 400

    Canvas {
        anchors.fill: parent
        onPaint: {
            var ctx = getContext("2d");
            ctx.reset();

            var centreX = width / 2;
            var centreY = height / 2;

            ctx.beginPath();
            ctx.fillStyle = "black";
            ctx.moveTo(centreX, centreY);
            ctx.arc(centreX, centreY, width / 4, 0, Math.PI * 0.5, false);
            ctx.lineTo(centreX, centreY);
            ctx.fill();

            ctx.beginPath();
            ctx.fillStyle = "red";
            ctx.moveTo(centreX, centreY);
            ctx.arc(centreX, centreY, width / 4, Math.PI * 0.5, Math.PI * 2, false);
            ctx.lineTo(centreX, centreY);
            ctx.fill();
        }
    }
}

I actually took the code for this from this answer, as Qt's Canvas implements the HTML5 Canvas API.我实际上从这个答案中获取了代码,因为 Qt 的 Canvas 实现了 HTML5 Canvas API。 This makes it really easy to find examples on the web;这使得在网络上找到示例变得非常容易; just search for "draw pie slice blah html5 canvas", for example.例如,只需搜索“绘制饼图切片等等 html5 画布”。

For the mouse detection, you'll have to brush off your maths skills...对于鼠标检测,你必须刷掉你的数学技能......

... or just steal the code from here . ...或者只是从这里窃取代码。 :) :)

Note that Canvas only repaints when it's resized, or when requestPaint() is called, so if you want to change the colour of a slice depending on the mouse position, you'll need to call that function to see the colour change.请注意,Canvas 仅在调整大小或调用requestPaint()时重新绘制,因此如果您想根据鼠标位置更改切片的颜色,则需要调用该函数以查看颜色变化。

Draw it using qml, you don't need the canvas.使用qml绘制它,您不需要画布。 As a guideline I usually go through Qt's examples before deciding on an implementation.作为指导方针,我通常在决定实现之前先浏览 Qt 的示例。 The code below can be found in "Shapes" example.下面的代码可以在“形状”示例中找到。

import QtQuick 2.11
import QtQuick.Shapes 1.15

Shape {
    width: 120
    height: 130
    anchors.bottom: parent.bottom
    anchors.right: parent.right
    // multisample, decide based on your scene settings
    layer.enabled: true
    layer.samples: 4

    ShapePath {
        fillColor: "black"
        strokeColor: "darkBlue"
        strokeWidth: 20
        capStyle: ShapePath.FlatCap

        PathAngleArc {
            centerX: 65; centerY: 95
            radiusX: 45; radiusY: 45
            startAngle: -180
            sweepAngle: 180
        }
    }
}

Use charts http://doc.qt.io/QtCharts/qtcharts-qmlmodule.html使用图表http://doc.qt.io/QtCharts/qtcharts-qmlmodule.html

import QtQuick 2.0
import QtCharts 2.0

ChartView {
width: 400 
height: 300
theme: ChartView.ChartThemeBrownSand
antialiasing: true

PieSeries {
    id: pieSeries
    PieSlice { label: "eaten"; value: 94.9 }
    PieSlice { label: "not yet eaten"; value: 5.1 }
}
}

Since the question was about drawing "pizza slices" and making each of them clickable , an important detail is mapping clicks to the right segment (aka the right "pizza slice").由于问题是关于绘制“披萨片”并使它们中的每一个都可点击,因此一个重要的细节是将点击映射到正确的部分(也就是正确的“披萨片”)。

None of the prior answers seem to contain any onClicked handling, so I offer yet another possibility.先前的答案似乎都没有包含任何onClicked处理,所以我提供了另一种可能性。 (All the prior answers are also valid, they just don't make it immediately clear where to intercept clicks.) (所有先前的答案也是有效的,他们只是没有立即清楚在哪里拦截点击。)

I had a similar case wherein I needed to slice a rectangle on a 45 degree diagonal, and detect whether clicks fall above or below the diagonal line.我有一个类似的案例,我需要在 45 度对角线上切割一个矩形,并检测点击是否落在对角线上方或下方。

Thankfully, it turns out that QML allows you to:幸运的是,事实证明 QML 允许您:

  • create a grid创建网格
  • apply a transform: Rotation to that grid应用transform: Rotation到那个网格
  • ... and then automatically your clicks "just work" ...然后你的点击会自动“正常工作”
    • (meaning: clicking on a 45-degree rotated rectangle maps as you would wish) (意思是:按你的意愿点击一个 45 度旋转的矩形地图)

The demo code renders a rotated grid like the following, and outputs (via console.log ) the color that you click on:演示代码呈现如下所示的旋转网格,并输出(通过console.log )您单击的颜色:

QML 矩形的旋转网格

The following has been tested on Ubuntu using Qt 5.14以下已在 Ubuntu 上使用 Qt 5.14 进行测试

import QtGraphicalEffects 1.12
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Universal 2.2
import QtQuick.Layouts 1.14

Item {
  height: 1000
  width: 2000

  GridLayout {
    id: grid
    columnSpacing: 0 // the default is non-zero!
    rowSpacing: 0
    anchors.centerIn: parent
    rows: 2
    columns: 2

    Rectangle {
      height: 200
      width: 200
      color: 'red'
      MouseArea {
        anchors.fill: parent
        onClicked: {
          console.log('red')
        }
      }
    }
    Rectangle {
      height: 200
      width: 200
      color: 'yellow'
      MouseArea {
        anchors.fill: parent
        onClicked: {
          console.log('yellow')
        }
      }
    }
    Rectangle {
      height: 200
      width: 200
      color: 'green'
      MouseArea {
        anchors.fill: parent
        onClicked: {
          console.log('green')
        }
      }
    }
    Rectangle {
      height: 200
      width: 200
      color: 'blue'
      MouseArea {
        anchors.fill: parent
        onClicked: {
          console.log('blue')
        }
      }
    }
    transform: Rotation {
      origin.x: grid.width * 0.5
      origin.y: grid.height * 0.5
      axis {
        x: 0
        y: 0
        z: 1
      }
      angle: 45
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM