Kivy ProgressBar-value doesn't get updated when kwargs' position switched.
I'm using Kivy (v-2.0.0) [Python (v-3.9.7)].
The problem
I noticed the unexpected behaviour (behavior) when initialized the ProgressBar with the attrs. max and value with different order such as ProgressBar(max = 1000, value = 450) or ProgressBar(value = 450, max = 1000). They both render different result.
What I tried but didn't work
I tried to bind the attr. "max" with the AliasProperty value, setting different cache values, but none of them seem to work for me. I think (not quite sure) this problem arises due to the setter method.
What seems to work
I changed the attr. value to BoundedNumericProperty as BoundedNumericProperty(0.0, min = 0, errorvalue = 0) and redefine it in the init as
def __init__(self, **kwargs):
#self._value = 0.
super(ProgressBar, self).__init__(**kwargs)
self.value = min(self.max, self.value) # To limit the upper-value of the attr: value within attr: max.
Now I got the result in both cases as expected.
Executable (for the original problem)
from kivy.app import runTouchApp
from kivy.uix.progressbar import ProgressBar
pb = ProgressBar(max = 1000, value = 450) # This works as intended.
#pb = ProgressBar(value = 450, max = 1000) # This does not work as intended.
print(f"{pb.max = }, {pb.value = }")
runTouchApp(pb)
Well, I noticed again this doesn't solve the issue completely, as the attr. value can be (made) unbounded above at runtime.
Looks to me like you are calling the super() in the wrong class. You should be seeing something in the logs about this.
No, actually I did it in source code of ProgressBar after observing that odd behaviour. Did you also notice that same behaviour after altering the position of kwargs ?
No, actually I did it in source code of
ProgressBarafter observing that odd behaviour. Did you also notice that same behaviour after altering the position of kwargs ?
Not the best practice on editing the source code of Kivy. Here is one example that works:
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.uix.progressbar import ProgressBar
class MyProgressBar(ProgressBar):
max = NumericProperty(20)
value = NumericProperty(50)
default = NumericProperty(1)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.value = min(self.max, self.value) if self.value <= self.max else self.default
class ProgressBarTest(App):
def build(self):
return MyProgressBar()
if __name__ == '__main__':
ProgressBarTest().run()
It looks like I failed to describe the problem properly. I ran the above code (Executable (for the original problem)) as described in the source code of ProgressBar. But when change the kwargs (as above) I noticed that behaviour.
Not a problem on my end:
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.uix.progressbar import ProgressBar
class MyProgressBar(ProgressBar):
max = NumericProperty(20)
value = NumericProperty(50)
default = NumericProperty(1)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.value = min(self.max, self.value) if self.value <= self.max else self.default
class ProgressBarTest(App):
def build(self):
return MyProgressBar(value=20, max=50)
if __name__ == '__main__':
ProgressBarTest().run()
Now try changing the direction. If there are other variables/functions you need from ProgressBar you just add them in there. Or write it like this:
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.uix.progressbar import ProgressBar
class MyProgressBar(ProgressBar):
max = NumericProperty(20)
value = NumericProperty(50)
default = NumericProperty(1)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.value = min(self.max, self.value) if self.value <= self.max else self.default
class ProgressBarTest(App):
def build(self):
root = MyProgressBar()
root.value = 20
root.max = 70
return root
if __name__ == '__main__':
ProgressBarTest().run()
Alas ! Yet again I failed to describe the problem,
Ok, when I run,
from kivy.app import runTouchApp
from kivy.uix.progressbar import ProgressBar
pb = ProgressBar(max = 1000, value = 450) # This works as intended.
print(f"{pb.max = }, {pb.value = }")
runTouchApp(pb)
I got, pb.max = 1000, pb.value = 450.
But when I did,
from kivy.app import runTouchApp
from kivy.uix.progressbar import ProgressBar
pb = ProgressBar(value = 450, max = 1000) # This does not work as intended.
print(f"{pb.max = }, {pb.value = }")
runTouchApp(pb)
I got, pb.max = 1000, pb.value = 100.0
Please, just let me know if this is an error from my side or really a bug.
Thank you! Now I understand the problem. I will look into the source code. But for now you can use:
from kivy.app import runTouchApp
from kivy.uix.progressbar import ProgressBar
from kivy.properties import NumericProperty
class MyProg(ProgressBar):
value = NumericProperty(0)
if __name__ == '__main__':
pb = MyProg(value=450, max=1000) # This does not work as intended.
print(f"{pb.max = }, {pb.value = }")
runTouchApp(pb)
Yes that's why I tried changing AliasProperty by BoundedNumericProperty.
As I had a conversation on Discord with the Core-Devs. They suggested updating the documentation page and being specific about what you said about placing the arguments in the right order.
I will argue that value should be allowed to be modified by user i.e. it should be a NumericProperty (or at least BoundedNumericProperty with min = 0 maybe) instead of the current AliasProperty.
This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have the means to take action. Please reach out if you have or find the answers we need so that we can investigate further.