Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Solved Rounded button with progress background fill

    QML and Qt Quick
    qml button progress mask clipping
    2
    3
    1588
    Loading More Posts
    • 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.
    • M
      markugra last edited by

      Hi,

      I would like to create a count-down button with rounded corners and a background that fills/empties proportionally to the elapsed time. Something like this:0_1516664109975_CountDownButton.png

      I thought I could do this using two rectangles as the button background where the black one has a width proportional to the time and the corners on the left would be clipped by the other Rectangle. Something like this:

      Button{
      	id: control
      	...
      	background: Rectangle {
      		id: backgroundRect
      		implicitWidth: 100
      		implicitHeight: 60
      		radius: height / 2
      		anchors.fill: parent
      		color: "gray"
      
      		Rectangle{
      			id: progressRect
      			anchors.verticalCenter: backgroundRect.verticalCenter
      			anchors.left: backgroundRect.left
      			clip: true
      			height: backgroundRect.height
      			width: relativeCounter*backgroundRect.width
      			color: "black"
      		}
      	}
      }
      

      However the clipping works only along the bounding box, i.e. the corners on the left are not rounded:
      0_1516665332755_CountDownButton_wrong.png

      I tried OpacityMask in the GraphicalEffects module, but I think I cannot use the parent rectangle as mask. I tried to work around it but could not get it to run. The last option I see is using Canvas and describing the round corners mathematically.

      I am new to QML so it is quite possible that I did something wrong in the steps I tried or that I am missing a simpler option.

      If anyone has an idea how it should work or can confirm that something does not work, I am grateful for any help.

      Thanks in advance

      raven-worx 1 Reply Last reply Reply Quote 0
      • raven-worx
        raven-worx Moderators @markugra last edited by raven-worx

        @markugra said in Rounded button with progress background fill:

        I tried OpacityMask in the GraphicalEffects module, but I think I cannot use the parent rectangle as mask.

        exactly, you need to place the button and the rectangle "beside the button on the same level"
        You could group the button and the rectangle into a custom component then.
        See the example in the docs and replace it analogous with your button and rectangle elements.

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        1 Reply Last reply Reply Quote 2
        • M
          markugra last edited by

          Thanks, I tried the OpacityMask again as you suggested and it works now. It took me a bit to get it right, because i) I had a warning about the recursive property in ShaderEffectSource needing to be set to "true" and ii) the mask size needs to be the same as the source size for it to work properly. After a while I noticed that i) originated from some code in the contentItem of the button using the ColorOverlay (in fact it was the same problem there i.e. I tried to apply it to the parent). To fix ii) I used a transparent frame so that the code now looks something like:

          background:
                  Item{
                      width: control.width
                      height: control.height
                      Rectangle{
                          id: progressFrame
                          anchors.fill: parent
                          color: "transparent"
                          visible: false
                          Rectangle{
                              id: progressRect
                              width: 0.7*parent.width
                              height: parent.height
                              anchors.verticalCenter: parent.verticalCenter
                              anchors.left: parent.left
                              color: "green"
                          }
                      }
                      Rectangle {
                          id: backgroundRect
                          anchors.fill: parent
                          radius: height / 2
                          color: "red"
                          visible: true
                      }
          
                      OpacityMask{
                      anchors.fill: progressFrame
                      source: progressFrame
                      maskSource: backgroundRect
                      }
                  }
          

          Resulting in:
          0_1516730617237_960aab10-96cd-4f9e-b86d-afd96504a439-image.png

          Thanks again!

          1 Reply Last reply Reply Quote 0
          • First post
            Last post