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. How to make slider with image
Forum Updated to NodeBB v4.3 + New Features

How to make slider with image

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
7 Posts 3 Posters 688 Views
  • 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.
  • L Offline
    L Offline
    linhnobi
    wrote on last edited by linhnobi
    #1

    I just want to make time slider like the image below!
    49032d55-5d32-4bfb-a649-baa7c0b83b78-image.png
    But I don't know how to make it by Qt Quick or Qt Quick integrate c++. Is anyone can make it please give me some guides??? Thanks so much

    L 1 Reply Last reply
    0
    • johngodJ Offline
      johngodJ Offline
      johngod
      wrote on last edited by
      #2

      Just try putting a regular slider inside a Image, it should work

      1 Reply Last reply
      1
      • L linhnobi

        I just want to make time slider like the image below!
        49032d55-5d32-4bfb-a649-baa7c0b83b78-image.png
        But I don't know how to make it by Qt Quick or Qt Quick integrate c++. Is anyone can make it please give me some guides??? Thanks so much

        L Offline
        L Offline
        lemons
        wrote on last edited by
        #3

        @linhnobi here a very basic example of @johngod suggestion:

        ApplicationWindow {
            width: 640
            height: 640
            visible: true
            title: "Simple Audio Slider Example"
        
            ColumnLayout {
                width: parent.width
        
                Slider {
                    id: audioSlider
                    value: audioTrack.progressValue
                    Layout.preferredHeight: 100
                    Layout.fillWidth: true
        
                    Text {
                        id: progressTime
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.left: parent.left
                        anchors.margins: 10
                        color: "white"
                        text: formatInterval(audioTrack.position)
                    }
        
                    Text {
                        id: totalTrackDuration
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.right: parent.right
                        anchors.margins: 10
                        color: "white"
                        text: formatInterval(audioTrack.duration)
                    }
        
                    onValueChanged: Qt.callLater(function () {
                        audioTrack.seek(value * audioTrack.duration)
                    })
        
                    Audio {
                        id: audioTrack
                        autoPlay: true
                        property double progressValue: position / duration
                        source: "https://upload.wikimedia.org/wikipedia/commons/6/63/Sagetyrtle_-_citystreet3_%28cc0%29_%28freesound%29.mp3"
                    }
        
                    background: Rectangle {
                        // optional change Rectangle to Image
                        id: backgroundImage
                        width: audioSlider.width
                        height: audioSlider.height
        
                        ColorOverlay {
                            id: greyOverlay
                            anchors.fill: backgroundImage
                            source: backgroundImage
                            color: "#80000000"
                        }
        
                        Rectangle {
                            width: audioSlider.visualPosition * parent.width
                            height: parent.height
                            color: "orange"
                            opacity: 0.3
                        }
                    }
        
                    handle: Item {
                        visible: false
                    }
                }
                RowLayout {
                    Button {
                        text: "Play"
                        onClicked: audioTrack.play()
                    }
                    Button {
                        text: "Pause"
                        onClicked: audioTrack.pause()
                    }
                }
            }
        
            function formatInterval(interval) {
                let seconds = Math.floor(interval / 1000)
                let hours = Math.floor(seconds / 3600)
                let minutes = Math.floor((seconds % 3600) / 60)
                seconds = seconds % 60
        
                const formattedHours = hours.toString().padStart(2, '0')
                const formattedMinutes = minutes.toString().padStart(2, '0')
                const formattedSeconds = seconds.toString().padStart(2, '0')
        
                return hours > 0 ? `${formattedHours}:${formattedMinutes}:${formattedSeconds}` : `${formattedMinutes}:${formattedSeconds}`
            }
        }
        
        
        L 2 Replies Last reply
        1
        • L lemons

          @linhnobi here a very basic example of @johngod suggestion:

          ApplicationWindow {
              width: 640
              height: 640
              visible: true
              title: "Simple Audio Slider Example"
          
              ColumnLayout {
                  width: parent.width
          
                  Slider {
                      id: audioSlider
                      value: audioTrack.progressValue
                      Layout.preferredHeight: 100
                      Layout.fillWidth: true
          
                      Text {
                          id: progressTime
                          anchors.verticalCenter: parent.verticalCenter
                          anchors.left: parent.left
                          anchors.margins: 10
                          color: "white"
                          text: formatInterval(audioTrack.position)
                      }
          
                      Text {
                          id: totalTrackDuration
                          anchors.verticalCenter: parent.verticalCenter
                          anchors.right: parent.right
                          anchors.margins: 10
                          color: "white"
                          text: formatInterval(audioTrack.duration)
                      }
          
                      onValueChanged: Qt.callLater(function () {
                          audioTrack.seek(value * audioTrack.duration)
                      })
          
                      Audio {
                          id: audioTrack
                          autoPlay: true
                          property double progressValue: position / duration
                          source: "https://upload.wikimedia.org/wikipedia/commons/6/63/Sagetyrtle_-_citystreet3_%28cc0%29_%28freesound%29.mp3"
                      }
          
                      background: Rectangle {
                          // optional change Rectangle to Image
                          id: backgroundImage
                          width: audioSlider.width
                          height: audioSlider.height
          
                          ColorOverlay {
                              id: greyOverlay
                              anchors.fill: backgroundImage
                              source: backgroundImage
                              color: "#80000000"
                          }
          
                          Rectangle {
                              width: audioSlider.visualPosition * parent.width
                              height: parent.height
                              color: "orange"
                              opacity: 0.3
                          }
                      }
          
                      handle: Item {
                          visible: false
                      }
                  }
                  RowLayout {
                      Button {
                          text: "Play"
                          onClicked: audioTrack.play()
                      }
                      Button {
                          text: "Pause"
                          onClicked: audioTrack.pause()
                      }
                  }
              }
          
              function formatInterval(interval) {
                  let seconds = Math.floor(interval / 1000)
                  let hours = Math.floor(seconds / 3600)
                  let minutes = Math.floor((seconds % 3600) / 60)
                  seconds = seconds % 60
          
                  const formattedHours = hours.toString().padStart(2, '0')
                  const formattedMinutes = minutes.toString().padStart(2, '0')
                  const formattedSeconds = seconds.toString().padStart(2, '0')
          
                  return hours > 0 ? `${formattedHours}:${formattedMinutes}:${formattedSeconds}` : `${formattedMinutes}:${formattedSeconds}`
              }
          }
          
          
          L Offline
          L Offline
          linhnobi
          wrote on last edited by
          #4

          @lemons I've tried this and it worked but the problem is when I use the Image just like this 57b6c0d4-bf00-4878-b1ee-321481923c51-image.png
          I don't know how to display it because when I tried to use 2 images with a gray one and a color one, the color one will be cropped

          1 Reply Last reply
          0
          • L lemons

            @linhnobi here a very basic example of @johngod suggestion:

            ApplicationWindow {
                width: 640
                height: 640
                visible: true
                title: "Simple Audio Slider Example"
            
                ColumnLayout {
                    width: parent.width
            
                    Slider {
                        id: audioSlider
                        value: audioTrack.progressValue
                        Layout.preferredHeight: 100
                        Layout.fillWidth: true
            
                        Text {
                            id: progressTime
                            anchors.verticalCenter: parent.verticalCenter
                            anchors.left: parent.left
                            anchors.margins: 10
                            color: "white"
                            text: formatInterval(audioTrack.position)
                        }
            
                        Text {
                            id: totalTrackDuration
                            anchors.verticalCenter: parent.verticalCenter
                            anchors.right: parent.right
                            anchors.margins: 10
                            color: "white"
                            text: formatInterval(audioTrack.duration)
                        }
            
                        onValueChanged: Qt.callLater(function () {
                            audioTrack.seek(value * audioTrack.duration)
                        })
            
                        Audio {
                            id: audioTrack
                            autoPlay: true
                            property double progressValue: position / duration
                            source: "https://upload.wikimedia.org/wikipedia/commons/6/63/Sagetyrtle_-_citystreet3_%28cc0%29_%28freesound%29.mp3"
                        }
            
                        background: Rectangle {
                            // optional change Rectangle to Image
                            id: backgroundImage
                            width: audioSlider.width
                            height: audioSlider.height
            
                            ColorOverlay {
                                id: greyOverlay
                                anchors.fill: backgroundImage
                                source: backgroundImage
                                color: "#80000000"
                            }
            
                            Rectangle {
                                width: audioSlider.visualPosition * parent.width
                                height: parent.height
                                color: "orange"
                                opacity: 0.3
                            }
                        }
            
                        handle: Item {
                            visible: false
                        }
                    }
                    RowLayout {
                        Button {
                            text: "Play"
                            onClicked: audioTrack.play()
                        }
                        Button {
                            text: "Pause"
                            onClicked: audioTrack.pause()
                        }
                    }
                }
            
                function formatInterval(interval) {
                    let seconds = Math.floor(interval / 1000)
                    let hours = Math.floor(seconds / 3600)
                    let minutes = Math.floor((seconds % 3600) / 60)
                    seconds = seconds % 60
            
                    const formattedHours = hours.toString().padStart(2, '0')
                    const formattedMinutes = minutes.toString().padStart(2, '0')
                    const formattedSeconds = seconds.toString().padStart(2, '0')
            
                    return hours > 0 ? `${formattedHours}:${formattedMinutes}:${formattedSeconds}` : `${formattedMinutes}:${formattedSeconds}`
                }
            }
            
            
            L Offline
            L Offline
            linhnobi
            wrote on last edited by
            #5

            @lemons here the issue that I mentioned above
            4ccaa250-79ef-45c1-b2fe-cda08a0c15d8-image.png

            L 1 Reply Last reply
            0
            • L linhnobi

              @lemons here the issue that I mentioned above
              4ccaa250-79ef-45c1-b2fe-cda08a0c15d8-image.png

              L Offline
              L Offline
              lemons
              wrote on last edited by lemons
              #6

              @linhnobi the easiest solution would be to add a grey rectangle with transparency over the not played track part (replacing the orange rectangle of already played audio). But this approach would lead to a large grey area above the entire slider and colors still being visible.

              the better solution is to use a ShaderEffect, which grey scales the unplayed area based on the audio position.
              Here the updated example:

              ApplicationWindow {
                  width: 640
                  height: 640
                  visible: true
                  title: "Simple Audio Slider Example"
              
                  ColumnLayout {
                      width: parent.width
              
                      Slider {
                          id: audioSlider
                          value: audioTrack.progressValue
                          Layout.preferredHeight: 100
                          Layout.fillWidth: true
              
                          Rectangle {
                              anchors.verticalCenter: parent.verticalCenter
                              anchors.left: parent.left
                              anchors.margins: 10
                              color: "grey"
                              opacity: 0.8
                              radius: 2
                              width: childrenRect.width
                              height: childrenRect.height
                              Text {
                                  id: progressTime
                                  padding: 5
                                  color: "white"
                                  text: formatInterval(audioTrack.position)
                              }
                          }
              
                          Rectangle {
                              anchors.verticalCenter: parent.verticalCenter
                              anchors.right: parent.right
                              anchors.margins: 10
                              color: "grey"
                              opacity: 0.8
                              radius: 2
                              width: childrenRect.width
                              height: childrenRect.height
              
                              Text {
                                  id: totalTrackDuration
                                  padding: 5
                                  color: "white"
                                  text: formatInterval(audioTrack.duration)
                              }
                          }
              
                          onValueChanged: Qt.callLater(function () {
                              audioTrack.seek(value * audioTrack.duration)
                          })
              
                          Audio {
                              id: audioTrack
                              autoPlay: true
                              property double progressValue: position / duration
                              source: "https://upload.wikimedia.org/wikipedia/commons/6/63/Sagetyrtle_-_citystreet3_%28cc0%29_%28freesound%29.mp3"
                          }
              
                          background: Image {
                              id: backgroundImage
                              width: audioSlider.width
                              height: audioSlider.height
                              fillMode: Image.PreserveAspectCrop
                              source: "https://ddgobkiprc33d.cloudfront.net/623e4d4f-c295-4b8c-940c-cf050a46cec4.png"
              
                              ShaderEffect {
                                  anchors.fill: parent
                                  property variant source: backgroundImage
                                  property real breakpoint: audioSlider.visualPosition
              
                                  fragmentShader: "
                                  uniform sampler2D source;
                                  uniform highp float breakpoint;
                                  varying highp vec2 qt_TexCoord0;
                                  void main() {
                                      highp vec4 p = texture2D(source, qt_TexCoord0);
                                      if (qt_TexCoord0.x > breakpoint) {
                                          highp float grey = dot(p.xyz, vec3(0.299, 0.587, 0.114));
                                          p = vec4(vec3(grey), p.w);
                                      }
                                      gl_FragColor = p;
                                  }"
                              }
                          }
              
                          handle: Item {
                              visible: false
                          }
                      }
                      RowLayout {
                          Button {
                              text: "Play"
                              onClicked: audioTrack.play()
                          }
                          Button {
                              text: "Pause"
                              onClicked: audioTrack.pause()
                          }
                      }
                  }
                  function formatInterval(interval) {
                      let seconds = Math.floor(interval / 1000)
                      let hours = Math.floor(seconds / 3600)
                      let minutes = Math.floor((seconds % 3600) / 60)
                      seconds = seconds % 60
              
                      const formattedHours = hours.toString().padStart(2, '0')
                      const formattedMinutes = minutes.toString().padStart(2, '0')
                      const formattedSeconds = seconds.toString().padStart(2, '0')
              
                      return hours > 0 ? `${formattedHours}:${formattedMinutes}:${formattedSeconds}` : `${formattedMinutes}:${formattedSeconds}`
                  }
              }
              
              
              L 1 Reply Last reply
              1
              • L lemons

                @linhnobi the easiest solution would be to add a grey rectangle with transparency over the not played track part (replacing the orange rectangle of already played audio). But this approach would lead to a large grey area above the entire slider and colors still being visible.

                the better solution is to use a ShaderEffect, which grey scales the unplayed area based on the audio position.
                Here the updated example:

                ApplicationWindow {
                    width: 640
                    height: 640
                    visible: true
                    title: "Simple Audio Slider Example"
                
                    ColumnLayout {
                        width: parent.width
                
                        Slider {
                            id: audioSlider
                            value: audioTrack.progressValue
                            Layout.preferredHeight: 100
                            Layout.fillWidth: true
                
                            Rectangle {
                                anchors.verticalCenter: parent.verticalCenter
                                anchors.left: parent.left
                                anchors.margins: 10
                                color: "grey"
                                opacity: 0.8
                                radius: 2
                                width: childrenRect.width
                                height: childrenRect.height
                                Text {
                                    id: progressTime
                                    padding: 5
                                    color: "white"
                                    text: formatInterval(audioTrack.position)
                                }
                            }
                
                            Rectangle {
                                anchors.verticalCenter: parent.verticalCenter
                                anchors.right: parent.right
                                anchors.margins: 10
                                color: "grey"
                                opacity: 0.8
                                radius: 2
                                width: childrenRect.width
                                height: childrenRect.height
                
                                Text {
                                    id: totalTrackDuration
                                    padding: 5
                                    color: "white"
                                    text: formatInterval(audioTrack.duration)
                                }
                            }
                
                            onValueChanged: Qt.callLater(function () {
                                audioTrack.seek(value * audioTrack.duration)
                            })
                
                            Audio {
                                id: audioTrack
                                autoPlay: true
                                property double progressValue: position / duration
                                source: "https://upload.wikimedia.org/wikipedia/commons/6/63/Sagetyrtle_-_citystreet3_%28cc0%29_%28freesound%29.mp3"
                            }
                
                            background: Image {
                                id: backgroundImage
                                width: audioSlider.width
                                height: audioSlider.height
                                fillMode: Image.PreserveAspectCrop
                                source: "https://ddgobkiprc33d.cloudfront.net/623e4d4f-c295-4b8c-940c-cf050a46cec4.png"
                
                                ShaderEffect {
                                    anchors.fill: parent
                                    property variant source: backgroundImage
                                    property real breakpoint: audioSlider.visualPosition
                
                                    fragmentShader: "
                                    uniform sampler2D source;
                                    uniform highp float breakpoint;
                                    varying highp vec2 qt_TexCoord0;
                                    void main() {
                                        highp vec4 p = texture2D(source, qt_TexCoord0);
                                        if (qt_TexCoord0.x > breakpoint) {
                                            highp float grey = dot(p.xyz, vec3(0.299, 0.587, 0.114));
                                            p = vec4(vec3(grey), p.w);
                                        }
                                        gl_FragColor = p;
                                    }"
                                }
                            }
                
                            handle: Item {
                                visible: false
                            }
                        }
                        RowLayout {
                            Button {
                                text: "Play"
                                onClicked: audioTrack.play()
                            }
                            Button {
                                text: "Pause"
                                onClicked: audioTrack.pause()
                            }
                        }
                    }
                    function formatInterval(interval) {
                        let seconds = Math.floor(interval / 1000)
                        let hours = Math.floor(seconds / 3600)
                        let minutes = Math.floor((seconds % 3600) / 60)
                        seconds = seconds % 60
                
                        const formattedHours = hours.toString().padStart(2, '0')
                        const formattedMinutes = minutes.toString().padStart(2, '0')
                        const formattedSeconds = seconds.toString().padStart(2, '0')
                
                        return hours > 0 ? `${formattedHours}:${formattedMinutes}:${formattedSeconds}` : `${formattedMinutes}:${formattedSeconds}`
                    }
                }
                
                
                L Offline
                L Offline
                linhnobi
                wrote on last edited by
                #7

                @lemons I've tried and it worked!!! Thank you very much. But I don't know to work with GLSL code to make this!! Can you recommend any materials for me to have better understanding ???

                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