Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Speedometer
Forum Updated to NodeBB v4.3 + New Features

Speedometer

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
22 Posts 4 Posters 2.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Darq

    Hello.

    I wanted to use this code to display the speedometer. Unfortunately, this speedometer is not displayed on the screen. What is the reason for this? What are the errors in the code?

    import QtQuick 2.0
    import QtQuick.Controls 1.4
    import QtQuick.Controls.Styles 1.4
    import QtQuick.Extras 1.4
    import QtQuick.Extras.Private 1.0

    Rectangle {
    width: 300
    height: 300
    color: "#494d53"

    CircularGauge {
        id: gauge
        anchors.centerIn: parent
        style: CircularGaugeStyle {
            id: style
    
            function degreesToRadians(degrees) {
                return degrees * (Math.PI / 180);
            }
    
            background: Canvas {
                onPaint: {
                    var ctx = getContext("2d");
                    ctx.reset();
    
                    ctx.beginPath();
                    ctx.strokeStyle = "#e34c22";
                    ctx.lineWidth = outerRadius * 0.02;
    
                    ctx.arc(outerRadius, outerRadius, outerRadius - ctx.lineWidth / 2,
                        degreesToRadians(valueToAngle(80) - 90), degreesToRadians(valueToAngle(100) - 90));
                    ctx.stroke();
                }
            }
    
            tickmark: Rectangle {
                visible: styleData.value < 80 || styleData.value % 10 == 0
                implicitWidth: outerRadius * 0.02
                antialiasing: true
                implicitHeight: outerRadius * 0.06
                color: styleData.value >= 80 ? "#e34c22" : "#e5e5e5"
            }
    
            minorTickmark: Rectangle {
                visible: styleData.value < 80
                implicitWidth: outerRadius * 0.01
                antialiasing: true
                implicitHeight: outerRadius * 0.03
                color: "#e5e5e5"
            }
    
            tickmarkLabel:  Text {
                font.pixelSize: Math.max(6, outerRadius * 0.1)
                text: styleData.value
                color: styleData.value >= 80 ? "#e34c22" : "#e5e5e5"
                antialiasing: true
            }
    
            needle: Rectangle {
                y: outerRadius * 0.15
                implicitWidth: outerRadius * 0.03
                implicitHeight: outerRadius * 0.9
                antialiasing: true
                color: "#e5e5e5"
            }
    
            foreground: Item {
                Rectangle {
                    width: outerRadius * 0.2
                    height: width
                    radius: width / 2
                    color: "#e5e5e5"
                    anchors.centerIn: parent
                }
            }
        }
    }
    

    }

    MarkkyboyM Offline
    MarkkyboyM Offline
    Markkyboy
    wrote on last edited by Markkyboy
    #2

    What does console say?

    Don't just sit there standing around, pick up a shovel and sweep up!

    I live by the sea, not in it.

    D 1 Reply Last reply
    0
    • D Darq

      Hello.

      I wanted to use this code to display the speedometer. Unfortunately, this speedometer is not displayed on the screen. What is the reason for this? What are the errors in the code?

      import QtQuick 2.0
      import QtQuick.Controls 1.4
      import QtQuick.Controls.Styles 1.4
      import QtQuick.Extras 1.4
      import QtQuick.Extras.Private 1.0

      Rectangle {
      width: 300
      height: 300
      color: "#494d53"

      CircularGauge {
          id: gauge
          anchors.centerIn: parent
          style: CircularGaugeStyle {
              id: style
      
              function degreesToRadians(degrees) {
                  return degrees * (Math.PI / 180);
              }
      
              background: Canvas {
                  onPaint: {
                      var ctx = getContext("2d");
                      ctx.reset();
      
                      ctx.beginPath();
                      ctx.strokeStyle = "#e34c22";
                      ctx.lineWidth = outerRadius * 0.02;
      
                      ctx.arc(outerRadius, outerRadius, outerRadius - ctx.lineWidth / 2,
                          degreesToRadians(valueToAngle(80) - 90), degreesToRadians(valueToAngle(100) - 90));
                      ctx.stroke();
                  }
              }
      
              tickmark: Rectangle {
                  visible: styleData.value < 80 || styleData.value % 10 == 0
                  implicitWidth: outerRadius * 0.02
                  antialiasing: true
                  implicitHeight: outerRadius * 0.06
                  color: styleData.value >= 80 ? "#e34c22" : "#e5e5e5"
              }
      
              minorTickmark: Rectangle {
                  visible: styleData.value < 80
                  implicitWidth: outerRadius * 0.01
                  antialiasing: true
                  implicitHeight: outerRadius * 0.03
                  color: "#e5e5e5"
              }
      
              tickmarkLabel:  Text {
                  font.pixelSize: Math.max(6, outerRadius * 0.1)
                  text: styleData.value
                  color: styleData.value >= 80 ? "#e34c22" : "#e5e5e5"
                  antialiasing: true
              }
      
              needle: Rectangle {
                  y: outerRadius * 0.15
                  implicitWidth: outerRadius * 0.03
                  implicitHeight: outerRadius * 0.9
                  antialiasing: true
                  color: "#e5e5e5"
              }
      
              foreground: Item {
                  Rectangle {
                      width: outerRadius * 0.2
                      height: width
                      radius: width / 2
                      color: "#e5e5e5"
                      anchors.centerIn: parent
                  }
              }
          }
      }
      

      }

      D Offline
      D Offline
      Darq
      wrote on last edited by
      #3
      This post is deleted!
      1 Reply Last reply
      0
      • MarkkyboyM Markkyboy

        What does console say?

        D Offline
        D Offline
        Darq
        wrote on last edited by
        #4

        @Markkyboy Does not display this item.

        MarkkyboyM 1 Reply Last reply
        0
        • D Darq

          @Markkyboy Does not display this item.

          MarkkyboyM Offline
          MarkkyboyM Offline
          Markkyboy
          wrote on last edited by
          #5

          @Darq - well, that is odd. Nothing displayed in console, that's odd.

          IF you copied your code from here; https://forum.qt.io/topic/113004/circulargauge-style which it looks like you did, did you fully read the response given on how to fix the problem?

          Also, I notice you have omitted the use of Window and have opened your code with a Rectangle instead.

          Don't just sit there standing around, pick up a shovel and sweep up!

          I live by the sea, not in it.

          D 1 Reply Last reply
          0
          • MarkkyboyM Markkyboy

            @Darq - well, that is odd. Nothing displayed in console, that's odd.

            IF you copied your code from here; https://forum.qt.io/topic/113004/circulargauge-style which it looks like you did, did you fully read the response given on how to fix the problem?

            Also, I notice you have omitted the use of Window and have opened your code with a Rectangle instead.

            D Offline
            D Offline
            Darq
            wrote on last edited by
            #6

            @Markkyboy Thank you for your help. I called the speedometer without using "CircularGauge". I want to trigger the movement of the pointer using "Rotation". How can I assign the needle offset angle to a given reading? I mean the following case: I have a reading of e.g. 0, an angle of 270 degrees, or a reading of 10, an angle of 300 degrees. How to make the pointer move smoothly to an angle of 270 when the value is 0, and when the value 10 appears, it moves smoothly to an angle of 300?

            1 Reply Last reply
            0
            • MarkkyboyM Offline
              MarkkyboyM Offline
              Markkyboy
              wrote on last edited by
              #7

              Earlier you told me nothing is displayed when building the app. Do I now assume you are seeing your app displayed on screen?, if so, what are you seeing?, what does console say now?

              The more info you give the better we progress, right now, you are trying to run before you can walk.

              Don't just sit there standing around, pick up a shovel and sweep up!

              I live by the sea, not in it.

              D 1 Reply Last reply
              0
              • MarkkyboyM Markkyboy

                Earlier you told me nothing is displayed when building the app. Do I now assume you are seeing your app displayed on screen?, if so, what are you seeing?, what does console say now?

                The more info you give the better we progress, right now, you are trying to run before you can walk.

                D Offline
                D Offline
                Darq
                wrote on last edited by
                #8

                @Markkyboy Previously, I didn't want to run the "CircularGauge" command, so I created the speedometer scale as a PNG image using the "Rectangle" command. Now I want to call up the speedometer needle. It is triggered similarly to the speedometer scales. But in order for it to move, I need to specify its "Rotation" command. This must be assigned to a numerical value and an offset angle. I'm downloading digital speed information and now I need to reflect it on the PNG speedometer scale. I just don't know how to do it.

                MarkkyboyM 1 Reply Last reply
                0
                • D Darq

                  @Markkyboy Previously, I didn't want to run the "CircularGauge" command, so I created the speedometer scale as a PNG image using the "Rectangle" command. Now I want to call up the speedometer needle. It is triggered similarly to the speedometer scales. But in order for it to move, I need to specify its "Rotation" command. This must be assigned to a numerical value and an offset angle. I'm downloading digital speed information and now I need to reflect it on the PNG speedometer scale. I just don't know how to do it.

                  MarkkyboyM Offline
                  MarkkyboyM Offline
                  Markkyboy
                  wrote on last edited by
                  #9

                  @Darq I think you should take a look at this GitHub, it offers all kinds of gauges, including one with needle movement. I have personally taken many cues from this code and have developed dozens of speedometer types. https://github.com/arunpkqt/CircularSlider
                  I think you can learn a lot from this code and build what you like.

                  Don't just sit there standing around, pick up a shovel and sweep up!

                  I live by the sea, not in it.

                  D 1 Reply Last reply
                  0
                  • johngodJ Offline
                    johngodJ Offline
                    johngod
                    wrote on last edited by
                    #10

                    @Darq Check this this post, I think this is what you want https://forum.qt.io/topic/147450/how-to-animate-the-angle-of-neddle-in-a-speedometer/5

                    1 Reply Last reply
                    0
                    • MarkkyboyM Markkyboy

                      @Darq I think you should take a look at this GitHub, it offers all kinds of gauges, including one with needle movement. I have personally taken many cues from this code and have developed dozens of speedometer types. https://github.com/arunpkqt/CircularSlider
                      I think you can learn a lot from this code and build what you like.

                      D Offline
                      D Offline
                      Darq
                      wrote on last edited by
                      #11

                      @Markkyboy How to limit the movement of the hand? What I want is for it not to show values ​​below 50. To sum up, the movement of the pointer would only start after reaching 50.

                      MarkkyboyM 1 Reply Last reply
                      0
                      • D Darq

                        @Markkyboy How to limit the movement of the hand? What I want is for it not to show values ​​below 50. To sum up, the movement of the pointer would only start after reaching 50.

                        MarkkyboyM Offline
                        MarkkyboyM Offline
                        Markkyboy
                        wrote on last edited by Markkyboy
                        #12

                        @Darq - without seeing what code you have so far, I don't know how to answer your question. Please post some working code, or what you have so far. It is much easier to see and have ideas when one can see some code.

                        EDIT: As I am already using CircularSlider from arunpkqt in several projects, I can easily adapt my code with your code and possibly work out a way to get what you want.

                        Don't just sit there standing around, pick up a shovel and sweep up!

                        I live by the sea, not in it.

                        D 1 Reply Last reply
                        0
                        • MarkkyboyM Markkyboy

                          @Darq - without seeing what code you have so far, I don't know how to answer your question. Please post some working code, or what you have so far. It is much easier to see and have ideas when one can see some code.

                          EDIT: As I am already using CircularSlider from arunpkqt in several projects, I can easily adapt my code with your code and possibly work out a way to get what you want.

                          D Offline
                          D Offline
                          Darq
                          wrote on last edited by Darq
                          #13

                          @Markkyboy
                          HmiImage {
                          id: pointer1
                          anchors.centerIn: parent
                          source: "icons/abc.png"
                          rotation: 2.25*XXX+225
                          }

                          XXX is my measured value
                          225 is an angle where the value is 0
                          2.25 is a degrees conversion, so for example, my value indicates 1, which corresponds to 2.25 degrees

                          MarkkyboyM 1 Reply Last reply
                          0
                          • D Darq

                            @Markkyboy
                            HmiImage {
                            id: pointer1
                            anchors.centerIn: parent
                            source: "icons/abc.png"
                            rotation: 2.25*XXX+225
                            }

                            XXX is my measured value
                            225 is an angle where the value is 0
                            2.25 is a degrees conversion, so for example, my value indicates 1, which corresponds to 2.25 degrees

                            MarkkyboyM Offline
                            MarkkyboyM Offline
                            Markkyboy
                            wrote on last edited by
                            #14

                            @Darq - this small bit of code is not enough for me to work with.

                            Don't just sit there standing around, pick up a shovel and sweep up!

                            I live by the sea, not in it.

                            D 1 Reply Last reply
                            0
                            • MarkkyboyM Markkyboy

                              @Darq - this small bit of code is not enough for me to work with.

                              D Offline
                              D Offline
                              Darq
                              wrote on last edited by
                              #15

                              @Markkyboy There is almost no more code there. There is only one more HmiImage defining the appearance of the shield (it loads the shields, i.e. a png file). In this code snippet there is only the "source" command which specifies the location of the png file. The png file has a scale drawn on it. The hint is called by the code above, which specifies its position (e.g. point 0 is at 225 degrees, so in the png file 0 is drawn at 225 degrees).

                              MarkkyboyM 1 Reply Last reply
                              0
                              • D Darq

                                @Markkyboy There is almost no more code there. There is only one more HmiImage defining the appearance of the shield (it loads the shields, i.e. a png file). In this code snippet there is only the "source" command which specifies the location of the png file. The png file has a scale drawn on it. The hint is called by the code above, which specifies its position (e.g. point 0 is at 225 degrees, so in the png file 0 is drawn at 225 degrees).

                                MarkkyboyM Offline
                                MarkkyboyM Offline
                                Markkyboy
                                wrote on last edited by
                                #16

                                @Darq - sorry, I just don't understand what you're trying to do. I can take plenty of wild guesses but I don't have the time to do so.

                                Making a functional speedometer requires a lot more code in my opinion. You could at the very least show an image/screenshot of what you have, otherwise I'm in the dark. At the very least, a mock up image of what you're wanting might be helpful.

                                What kind of speedo only functions when hitting 50?, what is the idea of this?, 50 what?, kmh?, mph?, kts?.....?

                                What is "icons/abc.png"?, what does it look like?

                                What is "hmiImage", where is that code?

                                Are you taking ANY cues from arunpkqt's application?

                                Seriously now, what you write here gives me very little to go on. I'm not sure I can help you.

                                Don't just sit there standing around, pick up a shovel and sweep up!

                                I live by the sea, not in it.

                                1 Reply Last reply
                                0
                                • MarkkyboyM Offline
                                  MarkkyboyM Offline
                                  Markkyboy
                                  wrote on last edited by Markkyboy
                                  #17

                                  Rather than leave you completely in the dark, Darq, here's some full code to make a working speedometer. Perhaps from this you can make it do what you want/require.

                                  import QtQuick
                                  import QtQuick.Controls
                                  
                                  Item {
                                      id: control
                                  
                                      property int trackWidth: 20
                                      property int progressWidth: 20
                                      property color trackColor: "#505050"
                                      property color progressColor: "#3a4ec4"
                                      property bool hideTrack: false
                                      property bool hideProgress: false
                                  
                                      property color handleColor: "#fefefe"
                                      property int handleWidth: 80
                                      property int handleHeight: 80
                                      property int handleRadius: 40
                                      property int handleVerticalOffset: 0
                                  
                                      property real startAngle: 0
                                      property real endAngle: 360
                                      property real minValue: 0.0
                                      property real maxValue: 1.0
                                  
                                      property real value: 0.0
                                      readonly property alias angle: internal.angle
                                  
                                  
                                      property real stepSize: 0
                                      property bool snap: false
                                      property Component handle: null
                                      readonly property alias pressed: trackMouse.pressed
                                  
                                      property bool interactive: true
                                      property alias cursorShape: trackMouse.cursorShape
                                  
                                      implicitWidth: 250
                                      implicitHeight: 250
                                  
                                      Binding {
                                          target: control
                                          property: "value"
                                          value: control.snap ? internal.snappedValue : internal.mapFromValue(startAngle, endAngle, minValue, maxValue, internal.angleProxy)
                                          when: internal.setUpdatedValue
                                      }
                                  
                                      QtObject {
                                          id: internal
                                  
                                          property point centerPt: Qt.point(control.width / 2, control.height / 2)
                                          property real baseRadius: Math.min(control.width, control.height) / 2 - Math.max(control.trackWidth, control.progressWidth) / 2
                                          property real actualSpanAngle: control.endAngle - control.startAngle
                                          property color transparentColor: "transparent"
                                          property color trackColor: control.trackColor
                                          property bool setUpdatedValue: false
                                          property real angleProxy: control.startAngle
                                          property real snappedValue: 0.0
                                          readonly property real angle: internal.mapFromValue(control.minValue, control.maxValue, control.startAngle, control.endAngle, control.value)
                                  
                                          function mapFromValue(inMin, inMax, outMin, outMax, inValue) {
                                              return (inValue - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
                                          }
                                  
                                          function updateAngle(angleVal) {
                                              if (angleVal < 0)
                                                  angleVal += 360;
                                  
                                              if ((angleVal >= control.startAngle) && (angleVal <= control.endAngle)) {
                                                  internal.setUpdatedValue = true;
                                                  internal.angleProxy = Qt.binding(function() { return angleVal; });
                                                  if(control.snap) {
                                                      var mappedValue = internal.mapFromValue(startAngle, endAngle, minValue, maxValue, internal.angleProxy)
                                                      var range = control.maxValue - control.minValue
                                                      var effectiveStep = 2
                                                      var actualVal = control.stepSize * Math.round(mappedValue / control.stepSize)
                                                      internal.snappedValue = actualVal
                                                  }
                                                  internal.setUpdatedValue = false;
                                              }
                                          }
                                      }
                                  
                                      MouseArea {
                                          anchors.fill: parent
                                          enabled: control.interactive
                                          onClicked: {
                                              var outerRadius = Math.min(control.width, control.height)/ 2
                                              var innerRadius = outerRadius - Math.max(control.trackWidth, 20);
                                              var clickedDistance = (mouseX - internal.centerPt.x) * (mouseX - internal.centerPt.x) + (mouseY - internal.centerPt.y) * (mouseY - internal.centerPt.y);
                                              var innerRadius2 = (innerRadius * innerRadius);
                                              var outerRadius2 = (outerRadius * outerRadius);
                                              var isOutOfInnerRadius = clickedDistance > innerRadius2;
                                              var inInSideOuterRadius = clickedDistance <= outerRadius2;
                                              if (inInSideOuterRadius && isOutOfInnerRadius) {
                                                  var angleDeg = Math.atan2(mouseY - internal.centerPt.y, mouseX - internal.centerPt.x) * 180 / Math.PI + 90;
                                                  internal.updateAngle(angleDeg);
                                              }
                                          }
                                      }
                                  
                                      // Handle Item
                                      Item {
                                          id: handleItem
                                          visible: control.interactive
                                  
                                          x: control.width / 2 - width / 2
                                          y: control.height / 2 - height / 2
                                          // make sure that the slider handle is always on top as we can set custom track or progress items
                                          z: 2
                                          width: control.handleWidth
                                          height: control.handleHeight
                                          antialiasing: true
                                          transform: [
                                              Translate {
                                                  y: -(Math.min(control.width, control.height) / 2) + Math.max(control.trackWidth, control.progressWidth) / 2 + control.handleVerticalOffset
                                              },
                                              Rotation {
                                                  angle: control.angle
                                                  origin.x: handleItem.width / 2
                                                  origin.y: handleItem.height / 2
                                              }
                                          ]
                                  
                                          MouseArea {
                                              id: trackMouse
                                              enabled: control.interactive
                                  
                                              function getVal() {
                                                  var handlePoint = mapToItem(control, trackMouse.mouseX, trackMouse.mouseY);
                                                  // angle in degrees
                                                  var angleDeg = Math.atan2(handlePoint.y - internal.centerPt.y, handlePoint.x - internal.centerPt.x) * 180 / Math.PI + 90;
                                                  internal.updateAngle(angleDeg);
                                              }
                                  
                                              anchors.fill: parent
                                              onPositionChanged: getVal()
                                              onClicked: getVal()
                                              cursorShape: Qt.ArrowCursor
                                          }
                                  
                                          Loader {
                                              id: handleLoader
                                  
                                              sourceComponent: control.handle ? handle : handleComponent
                                          }
                                      }
                                  
                                      /// Default handle component
                                      Component {
                                          id: handleComponent
                                  
                                          Rectangle {
                                              width: control.handleWidth
                                              height: control.handleHeight
                                              color: control.handleColor
                                              radius: control.handleRadius
                                              antialiasing: true
                                          }
                                      }
                                  }
                                  
                                  
                                  import QtQuick
                                  import QtQuick.Controls
                                  import "../components"
                                  
                                  Page {
                                      id: darqSpeedo
                                  
                                      allowedOrientations: Orientation.All // this is specific to SailfishOS and can likely be omitted.
                                  
                                      // imported from "../components"
                                      CircularSlider {
                                          id: speedometer
                                          interactive: false
                                          anchors.centerIn: parent
                                          width: 1000
                                          height: width
                                          value: 0
                                          startAngle: -108
                                          endAngle: 108
                                          minValue: 0
                                          maxValue: 180
                                          anchors {
                                              verticalCenterOffset: 200
                                              verticalCenter: parent.verticalCenter
                                              horizontalCenter: parent.horizontalCenter
                                          }
                                          // Tickmarks around gauge
                                          Repeater {
                                              model: 37
                                              Rectangle {
                                                  id: ones
                                                  width: 6
                                                  height: index % 4 === 0 ? 50 : 25
                                                  color: index % 4 === 0 ? "white" : "silver"
                                                  property real angle: index * 6
                                                  transform: [ Translate { x: parent.width / 2 - width / 2; y: -155 },
                                                      Rotation {
                                                          origin.x: parent.width / 2
                                                          origin.y: parent.height / 2
                                                          angle: ones.angle + parent.startAngle
                                                      }
                                                  ]
                                              }
                                          }
                                          // Numbers around gauge
                                          Repeater {
                                              model: 10
                                              Label {
                                                  id: digits
                                                  text: index * 20
                                                  color: "white"
                                                  font { bold: true; pixelSize: 48 }
                                                  property real angle: index * 24
                                                  transform: [
                                                      Translate {
                                                          x: parent.width / 2 - width / 2
                                                          y: -75 // distance from tickmarks
                                                      },
                                                      Rotation {
                                                          origin.x: parent.width / 2
                                                          origin.y: parent.height / 2
                                                          angle: digits.angle + parent.startAngle
                                                      }
                                                  ]
                                                  // keeps numbers horizontal
                                                  rotation: -digits.angle - parent.startAngle
                                              }
                                          }
                                          // Needle hub
                                          Rectangle {
                                              anchors.centerIn: speedometer
                                              width: 100
                                              height: width
                                              radius: width/2
                                              color: "#a0545454"
                                          }
                                          // Needle/pointer
                                          Repeater {
                                              model: 1
                                              Rectangle {
                                                  id: needle
                                                  width: 20
                                                  height: 450
                                                  color: "orange"
                                                  radius: 20
                                                  transform: [
                                                      Translate {
                                                          x: speedometer.width / 2 - width / 2
                                                          y: 50 // needle distance from centre
                                                      },
                                                      Rotation {
                                                          origin.x: speedometer.width / 2
                                                          origin.y: speedometer.height / 2
                                                          angle: speedometer.angle
                                                      }
                                                  ]
                                              }
                                          }
                                          // Animation for demo purposes
                                          SequentialAnimation on value {
                                              id: animation
                                              loops: Animation.Infinite
                                              running: true
                                              NumberAnimation { from: 0; to: 180; duration: 2000 }
                                              NumberAnimation { from: 180; to: 0; duration: 2000 }
                                          }
                                      }
                                  }
                                  
                                  

                                  NOTE: I use Page, as my apps are built for my mobile phone using SailfishOS. You don't have to use Page, you can likely swap it for Item instead.

                                  Screenshot_20231114_001.png

                                  Don't just sit there standing around, pick up a shovel and sweep up!

                                  I live by the sea, not in it.

                                  D S 2 Replies Last reply
                                  0
                                  • MarkkyboyM Markkyboy

                                    Rather than leave you completely in the dark, Darq, here's some full code to make a working speedometer. Perhaps from this you can make it do what you want/require.

                                    import QtQuick
                                    import QtQuick.Controls
                                    
                                    Item {
                                        id: control
                                    
                                        property int trackWidth: 20
                                        property int progressWidth: 20
                                        property color trackColor: "#505050"
                                        property color progressColor: "#3a4ec4"
                                        property bool hideTrack: false
                                        property bool hideProgress: false
                                    
                                        property color handleColor: "#fefefe"
                                        property int handleWidth: 80
                                        property int handleHeight: 80
                                        property int handleRadius: 40
                                        property int handleVerticalOffset: 0
                                    
                                        property real startAngle: 0
                                        property real endAngle: 360
                                        property real minValue: 0.0
                                        property real maxValue: 1.0
                                    
                                        property real value: 0.0
                                        readonly property alias angle: internal.angle
                                    
                                    
                                        property real stepSize: 0
                                        property bool snap: false
                                        property Component handle: null
                                        readonly property alias pressed: trackMouse.pressed
                                    
                                        property bool interactive: true
                                        property alias cursorShape: trackMouse.cursorShape
                                    
                                        implicitWidth: 250
                                        implicitHeight: 250
                                    
                                        Binding {
                                            target: control
                                            property: "value"
                                            value: control.snap ? internal.snappedValue : internal.mapFromValue(startAngle, endAngle, minValue, maxValue, internal.angleProxy)
                                            when: internal.setUpdatedValue
                                        }
                                    
                                        QtObject {
                                            id: internal
                                    
                                            property point centerPt: Qt.point(control.width / 2, control.height / 2)
                                            property real baseRadius: Math.min(control.width, control.height) / 2 - Math.max(control.trackWidth, control.progressWidth) / 2
                                            property real actualSpanAngle: control.endAngle - control.startAngle
                                            property color transparentColor: "transparent"
                                            property color trackColor: control.trackColor
                                            property bool setUpdatedValue: false
                                            property real angleProxy: control.startAngle
                                            property real snappedValue: 0.0
                                            readonly property real angle: internal.mapFromValue(control.minValue, control.maxValue, control.startAngle, control.endAngle, control.value)
                                    
                                            function mapFromValue(inMin, inMax, outMin, outMax, inValue) {
                                                return (inValue - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
                                            }
                                    
                                            function updateAngle(angleVal) {
                                                if (angleVal < 0)
                                                    angleVal += 360;
                                    
                                                if ((angleVal >= control.startAngle) && (angleVal <= control.endAngle)) {
                                                    internal.setUpdatedValue = true;
                                                    internal.angleProxy = Qt.binding(function() { return angleVal; });
                                                    if(control.snap) {
                                                        var mappedValue = internal.mapFromValue(startAngle, endAngle, minValue, maxValue, internal.angleProxy)
                                                        var range = control.maxValue - control.minValue
                                                        var effectiveStep = 2
                                                        var actualVal = control.stepSize * Math.round(mappedValue / control.stepSize)
                                                        internal.snappedValue = actualVal
                                                    }
                                                    internal.setUpdatedValue = false;
                                                }
                                            }
                                        }
                                    
                                        MouseArea {
                                            anchors.fill: parent
                                            enabled: control.interactive
                                            onClicked: {
                                                var outerRadius = Math.min(control.width, control.height)/ 2
                                                var innerRadius = outerRadius - Math.max(control.trackWidth, 20);
                                                var clickedDistance = (mouseX - internal.centerPt.x) * (mouseX - internal.centerPt.x) + (mouseY - internal.centerPt.y) * (mouseY - internal.centerPt.y);
                                                var innerRadius2 = (innerRadius * innerRadius);
                                                var outerRadius2 = (outerRadius * outerRadius);
                                                var isOutOfInnerRadius = clickedDistance > innerRadius2;
                                                var inInSideOuterRadius = clickedDistance <= outerRadius2;
                                                if (inInSideOuterRadius && isOutOfInnerRadius) {
                                                    var angleDeg = Math.atan2(mouseY - internal.centerPt.y, mouseX - internal.centerPt.x) * 180 / Math.PI + 90;
                                                    internal.updateAngle(angleDeg);
                                                }
                                            }
                                        }
                                    
                                        // Handle Item
                                        Item {
                                            id: handleItem
                                            visible: control.interactive
                                    
                                            x: control.width / 2 - width / 2
                                            y: control.height / 2 - height / 2
                                            // make sure that the slider handle is always on top as we can set custom track or progress items
                                            z: 2
                                            width: control.handleWidth
                                            height: control.handleHeight
                                            antialiasing: true
                                            transform: [
                                                Translate {
                                                    y: -(Math.min(control.width, control.height) / 2) + Math.max(control.trackWidth, control.progressWidth) / 2 + control.handleVerticalOffset
                                                },
                                                Rotation {
                                                    angle: control.angle
                                                    origin.x: handleItem.width / 2
                                                    origin.y: handleItem.height / 2
                                                }
                                            ]
                                    
                                            MouseArea {
                                                id: trackMouse
                                                enabled: control.interactive
                                    
                                                function getVal() {
                                                    var handlePoint = mapToItem(control, trackMouse.mouseX, trackMouse.mouseY);
                                                    // angle in degrees
                                                    var angleDeg = Math.atan2(handlePoint.y - internal.centerPt.y, handlePoint.x - internal.centerPt.x) * 180 / Math.PI + 90;
                                                    internal.updateAngle(angleDeg);
                                                }
                                    
                                                anchors.fill: parent
                                                onPositionChanged: getVal()
                                                onClicked: getVal()
                                                cursorShape: Qt.ArrowCursor
                                            }
                                    
                                            Loader {
                                                id: handleLoader
                                    
                                                sourceComponent: control.handle ? handle : handleComponent
                                            }
                                        }
                                    
                                        /// Default handle component
                                        Component {
                                            id: handleComponent
                                    
                                            Rectangle {
                                                width: control.handleWidth
                                                height: control.handleHeight
                                                color: control.handleColor
                                                radius: control.handleRadius
                                                antialiasing: true
                                            }
                                        }
                                    }
                                    
                                    
                                    import QtQuick
                                    import QtQuick.Controls
                                    import "../components"
                                    
                                    Page {
                                        id: darqSpeedo
                                    
                                        allowedOrientations: Orientation.All // this is specific to SailfishOS and can likely be omitted.
                                    
                                        // imported from "../components"
                                        CircularSlider {
                                            id: speedometer
                                            interactive: false
                                            anchors.centerIn: parent
                                            width: 1000
                                            height: width
                                            value: 0
                                            startAngle: -108
                                            endAngle: 108
                                            minValue: 0
                                            maxValue: 180
                                            anchors {
                                                verticalCenterOffset: 200
                                                verticalCenter: parent.verticalCenter
                                                horizontalCenter: parent.horizontalCenter
                                            }
                                            // Tickmarks around gauge
                                            Repeater {
                                                model: 37
                                                Rectangle {
                                                    id: ones
                                                    width: 6
                                                    height: index % 4 === 0 ? 50 : 25
                                                    color: index % 4 === 0 ? "white" : "silver"
                                                    property real angle: index * 6
                                                    transform: [ Translate { x: parent.width / 2 - width / 2; y: -155 },
                                                        Rotation {
                                                            origin.x: parent.width / 2
                                                            origin.y: parent.height / 2
                                                            angle: ones.angle + parent.startAngle
                                                        }
                                                    ]
                                                }
                                            }
                                            // Numbers around gauge
                                            Repeater {
                                                model: 10
                                                Label {
                                                    id: digits
                                                    text: index * 20
                                                    color: "white"
                                                    font { bold: true; pixelSize: 48 }
                                                    property real angle: index * 24
                                                    transform: [
                                                        Translate {
                                                            x: parent.width / 2 - width / 2
                                                            y: -75 // distance from tickmarks
                                                        },
                                                        Rotation {
                                                            origin.x: parent.width / 2
                                                            origin.y: parent.height / 2
                                                            angle: digits.angle + parent.startAngle
                                                        }
                                                    ]
                                                    // keeps numbers horizontal
                                                    rotation: -digits.angle - parent.startAngle
                                                }
                                            }
                                            // Needle hub
                                            Rectangle {
                                                anchors.centerIn: speedometer
                                                width: 100
                                                height: width
                                                radius: width/2
                                                color: "#a0545454"
                                            }
                                            // Needle/pointer
                                            Repeater {
                                                model: 1
                                                Rectangle {
                                                    id: needle
                                                    width: 20
                                                    height: 450
                                                    color: "orange"
                                                    radius: 20
                                                    transform: [
                                                        Translate {
                                                            x: speedometer.width / 2 - width / 2
                                                            y: 50 // needle distance from centre
                                                        },
                                                        Rotation {
                                                            origin.x: speedometer.width / 2
                                                            origin.y: speedometer.height / 2
                                                            angle: speedometer.angle
                                                        }
                                                    ]
                                                }
                                            }
                                            // Animation for demo purposes
                                            SequentialAnimation on value {
                                                id: animation
                                                loops: Animation.Infinite
                                                running: true
                                                NumberAnimation { from: 0; to: 180; duration: 2000 }
                                                NumberAnimation { from: 180; to: 0; duration: 2000 }
                                            }
                                        }
                                    }
                                    
                                    

                                    NOTE: I use Page, as my apps are built for my mobile phone using SailfishOS. You don't have to use Page, you can likely swap it for Item instead.

                                    Screenshot_20231114_001.png

                                    D Offline
                                    D Offline
                                    Darq
                                    wrote on last edited by
                                    #18

                                    @Markkyboy I don't mean the code for the entire speedometer. I want to restrict only this part of the code " rotation: 2.25*XXX+225 " to move in the angle range, e.g. from 225 to 135. I want there to be no movement in the range from 136 to 224 degrees. I don't know how to specify this in the code.

                                    MarkkyboyM 1 Reply Last reply
                                    0
                                    • D Darq

                                      @Markkyboy I don't mean the code for the entire speedometer. I want to restrict only this part of the code " rotation: 2.25*XXX+225 " to move in the angle range, e.g. from 225 to 135. I want there to be no movement in the range from 136 to 224 degrees. I don't know how to specify this in the code.

                                      MarkkyboyM Offline
                                      MarkkyboyM Offline
                                      Markkyboy
                                      wrote on last edited by
                                      #19

                                      @Darq said in Speedometer:

                                      ...... I want there to be no movement in the range from 136 to 224 degrees. I don't know how to specify this in the code.

                                      Sorry, right now I have no idea how to get what you want. I guess, like me, you will have to keep trying and playing until you succeed. I found little to no help with my own endeavours but fumbled my way through the code you see above. If I have an epiphany, I'll post it here but I make no promise.

                                      Could you explain why you want such a feature?

                                      Don't just sit there standing around, pick up a shovel and sweep up!

                                      I live by the sea, not in it.

                                      D 1 Reply Last reply
                                      0
                                      • MarkkyboyM Markkyboy

                                        @Darq said in Speedometer:

                                        ...... I want there to be no movement in the range from 136 to 224 degrees. I don't know how to specify this in the code.

                                        Sorry, right now I have no idea how to get what you want. I guess, like me, you will have to keep trying and playing until you succeed. I found little to no help with my own endeavours but fumbled my way through the code you see above. If I have an epiphany, I'll post it here but I make no promise.

                                        Could you explain why you want such a feature?

                                        D Offline
                                        D Offline
                                        Darq
                                        wrote on last edited by
                                        #20

                                        @Markkyboy Commands like "CircularSlider" don't work for me. This shield is called as png. The only problem is with the limitation of the "Rotation" command, so that the rotation is only within a specific range.

                                        1 Reply Last reply
                                        0
                                        • JonBJ JonB referenced this topic on
                                        • MarkkyboyM Markkyboy

                                          Rather than leave you completely in the dark, Darq, here's some full code to make a working speedometer. Perhaps from this you can make it do what you want/require.

                                          import QtQuick
                                          import QtQuick.Controls
                                          
                                          Item {
                                              id: control
                                          
                                              property int trackWidth: 20
                                              property int progressWidth: 20
                                              property color trackColor: "#505050"
                                              property color progressColor: "#3a4ec4"
                                              property bool hideTrack: false
                                              property bool hideProgress: false
                                          
                                              property color handleColor: "#fefefe"
                                              property int handleWidth: 80
                                              property int handleHeight: 80
                                              property int handleRadius: 40
                                              property int handleVerticalOffset: 0
                                          
                                              property real startAngle: 0
                                              property real endAngle: 360
                                              property real minValue: 0.0
                                              property real maxValue: 1.0
                                          
                                              property real value: 0.0
                                              readonly property alias angle: internal.angle
                                          
                                          
                                              property real stepSize: 0
                                              property bool snap: false
                                              property Component handle: null
                                              readonly property alias pressed: trackMouse.pressed
                                          
                                              property bool interactive: true
                                              property alias cursorShape: trackMouse.cursorShape
                                          
                                              implicitWidth: 250
                                              implicitHeight: 250
                                          
                                              Binding {
                                                  target: control
                                                  property: "value"
                                                  value: control.snap ? internal.snappedValue : internal.mapFromValue(startAngle, endAngle, minValue, maxValue, internal.angleProxy)
                                                  when: internal.setUpdatedValue
                                              }
                                          
                                              QtObject {
                                                  id: internal
                                          
                                                  property point centerPt: Qt.point(control.width / 2, control.height / 2)
                                                  property real baseRadius: Math.min(control.width, control.height) / 2 - Math.max(control.trackWidth, control.progressWidth) / 2
                                                  property real actualSpanAngle: control.endAngle - control.startAngle
                                                  property color transparentColor: "transparent"
                                                  property color trackColor: control.trackColor
                                                  property bool setUpdatedValue: false
                                                  property real angleProxy: control.startAngle
                                                  property real snappedValue: 0.0
                                                  readonly property real angle: internal.mapFromValue(control.minValue, control.maxValue, control.startAngle, control.endAngle, control.value)
                                          
                                                  function mapFromValue(inMin, inMax, outMin, outMax, inValue) {
                                                      return (inValue - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
                                                  }
                                          
                                                  function updateAngle(angleVal) {
                                                      if (angleVal < 0)
                                                          angleVal += 360;
                                          
                                                      if ((angleVal >= control.startAngle) && (angleVal <= control.endAngle)) {
                                                          internal.setUpdatedValue = true;
                                                          internal.angleProxy = Qt.binding(function() { return angleVal; });
                                                          if(control.snap) {
                                                              var mappedValue = internal.mapFromValue(startAngle, endAngle, minValue, maxValue, internal.angleProxy)
                                                              var range = control.maxValue - control.minValue
                                                              var effectiveStep = 2
                                                              var actualVal = control.stepSize * Math.round(mappedValue / control.stepSize)
                                                              internal.snappedValue = actualVal
                                                          }
                                                          internal.setUpdatedValue = false;
                                                      }
                                                  }
                                              }
                                          
                                              MouseArea {
                                                  anchors.fill: parent
                                                  enabled: control.interactive
                                                  onClicked: {
                                                      var outerRadius = Math.min(control.width, control.height)/ 2
                                                      var innerRadius = outerRadius - Math.max(control.trackWidth, 20);
                                                      var clickedDistance = (mouseX - internal.centerPt.x) * (mouseX - internal.centerPt.x) + (mouseY - internal.centerPt.y) * (mouseY - internal.centerPt.y);
                                                      var innerRadius2 = (innerRadius * innerRadius);
                                                      var outerRadius2 = (outerRadius * outerRadius);
                                                      var isOutOfInnerRadius = clickedDistance > innerRadius2;
                                                      var inInSideOuterRadius = clickedDistance <= outerRadius2;
                                                      if (inInSideOuterRadius && isOutOfInnerRadius) {
                                                          var angleDeg = Math.atan2(mouseY - internal.centerPt.y, mouseX - internal.centerPt.x) * 180 / Math.PI + 90;
                                                          internal.updateAngle(angleDeg);
                                                      }
                                                  }
                                              }
                                          
                                              // Handle Item
                                              Item {
                                                  id: handleItem
                                                  visible: control.interactive
                                          
                                                  x: control.width / 2 - width / 2
                                                  y: control.height / 2 - height / 2
                                                  // make sure that the slider handle is always on top as we can set custom track or progress items
                                                  z: 2
                                                  width: control.handleWidth
                                                  height: control.handleHeight
                                                  antialiasing: true
                                                  transform: [
                                                      Translate {
                                                          y: -(Math.min(control.width, control.height) / 2) + Math.max(control.trackWidth, control.progressWidth) / 2 + control.handleVerticalOffset
                                                      },
                                                      Rotation {
                                                          angle: control.angle
                                                          origin.x: handleItem.width / 2
                                                          origin.y: handleItem.height / 2
                                                      }
                                                  ]
                                          
                                                  MouseArea {
                                                      id: trackMouse
                                                      enabled: control.interactive
                                          
                                                      function getVal() {
                                                          var handlePoint = mapToItem(control, trackMouse.mouseX, trackMouse.mouseY);
                                                          // angle in degrees
                                                          var angleDeg = Math.atan2(handlePoint.y - internal.centerPt.y, handlePoint.x - internal.centerPt.x) * 180 / Math.PI + 90;
                                                          internal.updateAngle(angleDeg);
                                                      }
                                          
                                                      anchors.fill: parent
                                                      onPositionChanged: getVal()
                                                      onClicked: getVal()
                                                      cursorShape: Qt.ArrowCursor
                                                  }
                                          
                                                  Loader {
                                                      id: handleLoader
                                          
                                                      sourceComponent: control.handle ? handle : handleComponent
                                                  }
                                              }
                                          
                                              /// Default handle component
                                              Component {
                                                  id: handleComponent
                                          
                                                  Rectangle {
                                                      width: control.handleWidth
                                                      height: control.handleHeight
                                                      color: control.handleColor
                                                      radius: control.handleRadius
                                                      antialiasing: true
                                                  }
                                              }
                                          }
                                          
                                          
                                          import QtQuick
                                          import QtQuick.Controls
                                          import "../components"
                                          
                                          Page {
                                              id: darqSpeedo
                                          
                                              allowedOrientations: Orientation.All // this is specific to SailfishOS and can likely be omitted.
                                          
                                              // imported from "../components"
                                              CircularSlider {
                                                  id: speedometer
                                                  interactive: false
                                                  anchors.centerIn: parent
                                                  width: 1000
                                                  height: width
                                                  value: 0
                                                  startAngle: -108
                                                  endAngle: 108
                                                  minValue: 0
                                                  maxValue: 180
                                                  anchors {
                                                      verticalCenterOffset: 200
                                                      verticalCenter: parent.verticalCenter
                                                      horizontalCenter: parent.horizontalCenter
                                                  }
                                                  // Tickmarks around gauge
                                                  Repeater {
                                                      model: 37
                                                      Rectangle {
                                                          id: ones
                                                          width: 6
                                                          height: index % 4 === 0 ? 50 : 25
                                                          color: index % 4 === 0 ? "white" : "silver"
                                                          property real angle: index * 6
                                                          transform: [ Translate { x: parent.width / 2 - width / 2; y: -155 },
                                                              Rotation {
                                                                  origin.x: parent.width / 2
                                                                  origin.y: parent.height / 2
                                                                  angle: ones.angle + parent.startAngle
                                                              }
                                                          ]
                                                      }
                                                  }
                                                  // Numbers around gauge
                                                  Repeater {
                                                      model: 10
                                                      Label {
                                                          id: digits
                                                          text: index * 20
                                                          color: "white"
                                                          font { bold: true; pixelSize: 48 }
                                                          property real angle: index * 24
                                                          transform: [
                                                              Translate {
                                                                  x: parent.width / 2 - width / 2
                                                                  y: -75 // distance from tickmarks
                                                              },
                                                              Rotation {
                                                                  origin.x: parent.width / 2
                                                                  origin.y: parent.height / 2
                                                                  angle: digits.angle + parent.startAngle
                                                              }
                                                          ]
                                                          // keeps numbers horizontal
                                                          rotation: -digits.angle - parent.startAngle
                                                      }
                                                  }
                                                  // Needle hub
                                                  Rectangle {
                                                      anchors.centerIn: speedometer
                                                      width: 100
                                                      height: width
                                                      radius: width/2
                                                      color: "#a0545454"
                                                  }
                                                  // Needle/pointer
                                                  Repeater {
                                                      model: 1
                                                      Rectangle {
                                                          id: needle
                                                          width: 20
                                                          height: 450
                                                          color: "orange"
                                                          radius: 20
                                                          transform: [
                                                              Translate {
                                                                  x: speedometer.width / 2 - width / 2
                                                                  y: 50 // needle distance from centre
                                                              },
                                                              Rotation {
                                                                  origin.x: speedometer.width / 2
                                                                  origin.y: speedometer.height / 2
                                                                  angle: speedometer.angle
                                                              }
                                                          ]
                                                      }
                                                  }
                                                  // Animation for demo purposes
                                                  SequentialAnimation on value {
                                                      id: animation
                                                      loops: Animation.Infinite
                                                      running: true
                                                      NumberAnimation { from: 0; to: 180; duration: 2000 }
                                                      NumberAnimation { from: 180; to: 0; duration: 2000 }
                                                  }
                                              }
                                          }
                                          
                                          

                                          NOTE: I use Page, as my apps are built for my mobile phone using SailfishOS. You don't have to use Page, you can likely swap it for Item instead.

                                          Screenshot_20231114_001.png

                                          S Offline
                                          S Offline
                                          Sattiy
                                          wrote on last edited by
                                          #21

                                          @Markkyboy Can You Please specify which file is which file so i can integrate it accordingly like which is main.qml file here

                                          MarkkyboyM 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved