Shape { id: trackShape height: appWin.height layer.enabled: true layer.samples: 8 visible: !appWin.hideTrack width: appWin.width ShapePath { id: trackShapePath capStyle: appWin.capStyle fillColor: internal.transparentColor strokeColor: appWin.trackColor strokeWidth: appWin.trackWidth PathAngleArc { centerX: appWin.width / 2 centerY: appWin.height / 2 radiusX: internal.baseRadius radiusY: internal.baseRadius startAngle: appWin.startAngle - 90 sweepAngle: internal.actualSpanAngle } } }
Shape { id: trackShape height: appWin.size width: appWin.size layer.enabled: true layer.samples: 8 rotation: 180 ShapePath { id: trackShapePath capStyle: Qt.FlatCap fillColor: "transparent" strokeColor: "#333333" strokeWidth: pelData.mainCircleBorderSize PathAngleArc { centerX: appWin.size / 2 centerY: appWin.size / 2 radiusX: Math.min(appWin.size, appWin.size) / 2 - Math.max(appWin.trackWidth, appWin.progressWidth) / 2 radiusY: Math.min(appWin.size, appWin.size) / 2 - Math.max(appWin.trackWidth, appWin.progressWidth) / 2 startAngle: appWin.startAngle - 90 sweepAngle: 320 - 40 } } } Rectangle { id: mainForeground z: 1 anchors.centerIn: mainItem height: pelData.centralCircleRadius width: pelData.centralCircleRadius color: "gray" border.width: pelData.secondCircleBorderSize border.color: "#505050" radius: height / 2 visible: false Text { id: textValue z: 1 anchors.centerIn: parent text: pelData.currentValue font.pixelSize: pelData.textValueSize font.bold: true } } Repeater { id: repeaterTickMark model: pelData.gaugeDataModel anchors.fill: parent delegate: Rectangle { width: model.eWidth height: model.eHeight color: model.eColorTickMark antialiasing: true function major() { if(model.eWithText) return true return false } Rectangle { anchors.fill: parent anchors.topMargin: major() ? 160 : 165 anchors.bottomMargin: major() ? 3 : 23 color: "blue" Component.onCompleted: { console.log(model.eAngle, model.index, model.eWidth, model.eWithText) } } transform: [ Rotation { angle: model.eAngle }, Translate { x: mainItem.width / 2 y: mainItem.height / 2 } ] } }
import QtQuickimport QtQuick.Controlsimport QtQuick.ShapesItem { id: appWin property int progressWidth: 20 property int trackWidth: 3 property int handleHeight: 22 property int handleWidth: 22 property real outerRadius: 15.0 property real minorInsetRadius: outerRadius - 20 property real majorInsetRadius: outerRadius - 20 property real labelInsetRadius: outerRadius - 30 // control param property double minimumValue: 0.0 property double maximumValue: 160.0 property real startAngle: 40 property real endAngle: 320 property double value property int size: appWin.height property real needleRotation: { var percentage = (appWin.value - appWin.minimumValue) / (appWin.maximumValue - appWin.minimumValue); appWin.startAngle + percentage * Math.abs(appWin.endAngle - appWin.startAngle); } Item { id: mainItem anchors.horizontalCenter: appWin.horizontalCenter anchors.verticalCenter: appWin.verticalCenter height: appWin.size width: appWin.size Rectangle { id: mianBackgraund height: appWin.size width: appWin.size color: "gray" radius: height / 2 } Shape { id: trackShape height: appWin.size width: appWin.size layer.enabled: true layer.samples: 8 rotation: 180 // перевернуть обьект по вертикали ShapePath { id: trackShapePath capStyle: Qt.FlatCap // закругленные концы дуги fillColor: "transparent" // цвет заполнения внутри круга strokeColor: "#505050" // цвет внешнего кольца(границы) strokeWidth: 15 // толщина внешней границы PathAngleArc { centerX: appWin.size / 2 // центровка для обоих точек centerY: appWin.size / 2 radiusX: Math.min(appWin.size, appWin.size) / 2 - Math.max(appWin.trackWidth, appWin.progressWidth) / 2 radiusY: Math.min(appWin.size, appWin.size) / 2 - Math.max(appWin.trackWidth, appWin.progressWidth) / 2 startAngle: appWin.startAngle - 90 // на сколько будет повернут обьект(все зависит от начальной точки) sweepAngle: 320 - 40 // угол актуального пропуска в дуге(будет виден пролет от 40 до 320 градусов) } } } // Текст со значением куда повернута стрелка Text { id: textValue z: 1 anchors.centerIn: mainItem text: value.toFixed(1) font.pixelSize: 35 font.bold: true } // В нем мы будем создавать шкалы минутной величины(если мажорные тики это 0, 50, 100 и так далее, то для минорных это 10,20,30) Shape { id: minorTickMarketShape height: appWin.size width: appWin.size layer.enabled: true layer.samples: 8// rotation: 180 // перевернуть обьект по вертикали ShapePath { id: minorTickMarketShapePath capStyle: Qt.FlatCap // закругленные концы дуги fillColor: "transparent" // цвет заполнения внутри круга strokeColor: "blue" // цвет внешнего кольца(границы) strokeWidth: 10 // толщина внешней границы PathAngleArc { id: pathAngleArc centerX: appWin.size / 2 // центровка для обоих точек centerY: appWin.size / 2 radiusX: Math.min(appWin.size, appWin.size) / 2 - Math.max(appWin.trackWidth, 50) / 2 radiusY: Math.min(appWin.size, appWin.size) / 2 - Math.max(appWin.trackWidth, 50) / 2 startAngle: appWin.startAngle - 90 // на сколько будет повернут обьект(все зависит от начальной точки) sweepAngle: 320 - 40 // угол актуального пропуска в дуге(будет виден пролет от 40 до 320 градусов) } PathMultiline { paths: [ [Qt.point(minorTickMarketShape.height / 2, minorTickMarketShape.width / 2), Qt.point(50, 220)], [Qt.point(50.5, 80.12472), Qt.point(50.95, 80.90414)] ] } } } Repeater { id: tickmarkRepeater model: 7 anchors.fill: parent property real p: Math.abs(135 - (-135)) / (tickmarkRepeater.model - 1) delegate: Loader { id: tickmarkLoader x: appWin.width / 2 y: appWin.height / 2 sourceComponent: tickmark transform: [ Rotation { angle: ((-135) + 360 + (index * tickmarkRepeater.p) ) }, Translate { x: Math.sin(((-135) + 180 + index * tickmarkRepeater.p) * (Math.PI / 180)) * appWin.majorInsetRadius * -1 y: Math.cos(((-135) + 180 + index * tickmarkRepeater.p) * (Math.PI / 180)) * appWin.majorInsetRadius } ] } } // Стрелка Rectangle { id: needle width: 10 height: trackShape.height / 2 color: "#FFac89" radius: width / 2 antialiasing: true transform: [ Rotation { angle: needleRotation }, Translate { x: mainItem.width / 2 y: mainItem.height / 2 } ] } } Behavior on value { NumberAnimation { easing.overshoot: 1.2 duration: 5000 easing.type: Easing.OutBack } }}
import QtQuick 2.15import QtQuick.Controls 2.15import QtQuick.Window 2.15import QtQuick.Layouts 1.3import QtQuick.Shapes 1.15 Window { readonly property real quarterLength: 50 readonly property real minuteLength: 20 width: 640 height: 480 visible: true title: qsTr("Hello World") /* Shape { id: circle anchors.centerIn: parent ShapePath { strokeColor: "red" PathAngleArc { radiusX: Math.min(window.width, window.height) / 2 radiusY: radiusX startAngle: 0 sweepAngle: 360 } } } */ Rectangle { id: circle anchors.centerIn: parent width: Math.min(parent.width, parent.height) height: width radius: width / 2 border.color: "red" } Repeater { id: tickmarks model: 12 Shape { required property int index readonly property real phi: index * 2 * Math.PI / tickmarks.count readonly property real polarX: Math.cos(phi) readonly property real polarY: Math.sin(phi) x: circle.radius * polarX y: circle.radius * polarY transform: Translate { x: circle.x + circle.radius y: circle.y + circle.radius } ShapePath { strokeColor: "blue" strokeWidth: 1 PathLine { readonly property real tickmarkLength: index % 3 == 0 ? quarterLength : minuteLength relativeX: -polarX * tickmarkLength relativeY: -polarY * tickmarkLength } } } }}
Item{ id: appWin property int progressWidth: 20 property int trackWidth: 7 property int size: 200 Item { id: mainItem anchors.horizontalCenter: appWin.horizontalCenter anchors.verticalCenter: appWin.verticalCenter height: appWin.size width: appWin.size rotation: 180 Rectangle { id: mianBackgraund height: appWin.size width: appWin.size color: "transparent" radius: height / 2 } Shape { id: trackShape height: appWin.size width: appWin.size layer.enabled: true layer.samples: 8 ShapePath { id: trackShapePath capStyle: Qt.FlatCap fillColor: "transparent" strokeColor: "#333333" strokeWidth: 7 PathAngleArc { centerX: appWin.size / 2 centerY: appWin.size / 2 radiusX: Math.min(appWin.size, appWin.size) / 2 - Math.max(appWin.trackWidth, appWin.progressWidth) / 2 radiusY: Math.min(appWin.size, appWin.size) / 2 - Math.max(appWin.trackWidth, appWin.progressWidth) / 2 startAngle: 290 sweepAngle: 320 } } } Rectangle { id: mainForeground z: 1 anchors.centerIn: mainItem height: 78 width: 78 color: "transparent" border.width: 3 border.color: "#333333" radius: height / 2 } Repeater { id: repeaterTickMark model: 9 anchors.fill: parent delegate: Rectangle { width: model.eWidth height: trackShape.height / 2 - 7 color: "#00000000" Rectangle { anchors.fill: parent// anchors.topMargin: model.eMajorTickMark ? 160 : 165 // TODO: rewrite// anchors.bottomMargin: model.eMajorTickMark ? 0 : 23// color: model.eColorTickMark } transform: [ Rotation {// angle: model.eAngle }, Translate { x: mainItem.width / 2 y: mainItem.height / 2 } ] } } Rectangle { id: needle width: 5 height: trackShape.height / 2 // TODO: rewrite color: "transparent" antialiasing: true Rectangle { anchors.fill: parent anchors.topMargin: mainForeground.height / 2 + 1 color: "#ffffff" } transform: [ Rotation {// angle: pelData.angleNeedle }, Translate { x: mainItem.width / 2 y: mainItem.height / 2 } ] } }}
Rectangle { id: circle anchors.centerIn: parent width: Math.min(parent.width, parent.height) height: width radius: width / 2 border.color: "red" Repeater { id: tickmarks model: 12 Shape { required property int index readonly property real phi: index * 2 * Math.PI / tickmarks.count readonly property real polarX: Math.cos(phi) readonly property real polarY: Math.sin(phi) x: circle.radius * polarX y: circle.radius * polarY transform: Translate { x: /*circle.x +*/ circle.radius y: /*circle.y +*/ circle.radius } ShapePath { strokeColor: "blue" strokeWidth: 1 PathLine { readonly property real tickmarkLength: index % 3 == 0 ? quarterLength : minuteLength relativeX: -polarX * tickmarkLength relativeY: -polarY * tickmarkLength } } } } }