0

enter image description here

I am trying to make a custom progress bar with 2 images in Kivy.

self.progress_bar.width = self.size[0]*self.value_normalized

What I am doing now is to stretch the filled img from left to right according to the value_normalized, but I realized that it should not be like that.

Is there a way to show certain proportion of an image in Kivy?

BerryMan
  • 145
  • 1
  • 15
  • I come from the `PyQt`/`PySide` world here but isn't there an option to just inherit from kivy's `ProgressBar` and alter the way chunks look? If that's not possible one way to deal with the situation would be do have an image for certain progress values and then load each once the respective value has been reached. This is dirty but should work. – rbaleksandar Oct 05 '18 at 02:37
  • Check [this](https://stackoverflow.com/questions/50543028/how-to-make-circular-progress-bar-in-kivy) answer on how to create a custom progress bar. – rbaleksandar Oct 05 '18 at 02:39
  • @rbaleksandar That link is where I made a current one. However, I could not find a way to do it with an image without stretching the image. – BerryMan Oct 05 '18 at 03:07
  • You can put the `Image` in a `StencilView`. That limits the drawing of any `Widget` to the bounds of the `StencilView`. I suspect that you could adjust the `width` of the `StencilView` to just show as much of the `Image` as you desired. – John Anderson Oct 05 '18 at 04:40
  • @JohnAnderson I tried to use StencilView, but since there is no proper example, I still couldn't figured out how to do this. Could you please show me some codes? – BerryMan Oct 10 '18 at 08:12

1 Answers1

1

I have your code from a previous question, and have adapted that to use a StencilView. Note that I have abandoned extending ProgressBar, and your CLS_PROGRESS_BAR now simply extends FloatLayout. That makes it easier to define the layout of your CLS_PROGRESS_BAR. Here is the code:

from kivy.app import App
from kivy.properties import StringProperty, NumericProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.lang.builder import Builder
from kivy.clock import Clock


class CLS_PROGRESS_BAR(FloatLayout):
    background = StringProperty(None)
    progress_image = StringProperty(None)
    max = NumericProperty(0.0)

    def __init__(self, font_size=20, **kwargs):
        super(CLS_PROGRESS_BAR, self).__init__(**kwargs)
        self.progress_event = None
        self.font_size = font_size
        self.firstDraw = True
        self.pbi = None
        self.rect = None
        self.bgi = None
        self.value = 0.0
        self.value_normalized = 0.0

        self.progress_event = Clock.schedule_interval(self._progress, 0.5)

    def draw(self):
        if self.firstDraw:
            self.ids.bgi.source=self.background
            self.ids.pbi.source = self.progress_image
            self.ids.lab.font_size = self.font_size
            self.ids.lab.text = str(int(self.value_normalized*100)) + "%"
            self.ids.sten.width = self.size[0]*self.value_normalized
            self.firstDraw = False
        else:
            self.ids.lab.text = str(int(self.value_normalized*100)) + "%"
            self.ids.sten.width = self.size[0]*self.value_normalized

    def set_value(self, value):
        self.value = value
        self.value_normalized = self.value / self.max
        self.draw()

    def _progress(self, dt):
        if self.value < self.max - 1:
            self.set_value(self.value + 1)
        else:
            self.set_value(self.max)
            self.progress_event.cancel()


# Demo
class Main(App):

    def build(self):
        container = Builder.load_string(
            '''
<CLS_PROGRESS_BAR>:
    Image:
        id: bgi
        allow_stretch: True
        keep_ratio: False
    StencilView:
        id: sten
        size_hint: (None, None)
        size: (0, root.height)
        Image:
            id: pbi
            allow_stretch: True
            keep_ratio: False
            size_hint: (None, None)
            size: (root.width, lab.height)
            pos: (root.pos[0], root.pos[1] + (root.height - lab.height)/2.0)
    Label:
        id: lab
        text: '0%'
        size_hint: (None, None)
        size: self.texture_size
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}

CLS_PROGRESS_BAR:
    size_hint: (None, None)
    height: 100
    width: 500
    max: 100
    background: 'empty.png'
    progress_image: 'filled.png'
    ''')

        return container


if __name__ == '__main__':
    Main().run()
John Anderson
  • 35,991
  • 4
  • 13
  • 36