【问题标题】:Draw an arc/circle sector in QML?在 QML 中绘制圆弧/圆扇区?
【发布时间】:2014-11-20 14:14:53
【问题描述】:

我知道可以使用以下代码在 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
}

我的问题是:如果我需要画一个圆的扇区怎么办。 (Pizza Slices)并使这些切片中的每一个都可点击?我可以只使用 QML 吗?

【问题讨论】:

    标签: qt qml draw geometry sector


    【解决方案1】:

    是的,使用 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();
            }
        }
    }
    

    实际上,我从this 答案中获取了代码,因为 Qt 的 Canvas 实现了 HTML5 Canvas API。这使得在网络上查找示例变得非常容易;例如,只需搜索“draw pie slice blah html5 canvas”。

    对于鼠标检测,你必须放弃你的数学技能......

    ...或者只是从here 窃取代码。 :)

    请注意,Canvas 仅在调整大小或调用 requestPaint() 时才会重新绘制,因此如果您想根据鼠标位置更改切片的颜色,则需要调用该函数以查看颜色变化.

    【讨论】:

      【解决方案2】:

      使用 qml 绘制,不需要画布。作为指导,我通常会在决定实现之前查看 Qt 的示例。下面的代码可以在“形状”示例中找到。

      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
              }
          }
      }
      

      【讨论】:

        【解决方案3】:

        使用图表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 }
        }
        }
        

        【讨论】:

        • 许可警告!我们这些编写商业代码的人需要注意:与大多数 Qt 不同,QtCharts 未获得 LGPL 许可。如果您的产品是封闭源代码,则需要商业 Qt 许可证才能使用 QtCharts。
        【解决方案4】:

        由于问题是关于绘制“披萨片”并让它们中的每一个都可点击,因此一个重要的细节是将点击映射到正确的片段(也就是正确的“披萨片”)。

        之前的答案似乎都不包含任何onClicked 处理,所以我提供了另一种可能性。 (所有之前的答案也是有效的,只是没有立即明确在哪里拦截点击。)

        我有一个类似的案例,我需要在 45 度对角线上切割一个矩形,并检测点击是落在对角线之上还是之下。

        谢天谢地,事实证明 QML 允许您:

        • 创建网格
        • transform: Rotation 应用于该网格
        • ... 然后自动点击“正常工作”
          • (意思是:点击一个45度旋转的矩形地图,随心所欲)

        演示代码呈现如下旋转网格,并输出(通过console.log)您单击的颜色:

        以下内容已在 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
            }
          }
        }
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-03
          • 1970-01-01
          相关资源
          最近更新 更多