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

How to make slider with image

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
7 Posts 3 Posters 782 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