I’m trying to make a class that would be a Slider + 2 Labels, one label showing the value of the slider, and one showing the name of the slider. The goal is to reuse this in lieu of Slider when convinient.
I am ending up creating properties in the my class MySlider reflecting the ones I am interested in in Slider. If, for example, I wanted to be able to also specify the color of the value label, I could do the same, add a property “value_label_color” to MySlider and set the label’s color in on_value_label_color()… Then in the kv file I would do something like that:
value_label_color: 1,0,1,0.15
This would work but could be very long if I had many widgets in my MySlider class.
I thought there may be a way to avoid all this and directly access the label’s color from the kv file, so I could do something like the following?
MySlider: orientation: 'vertical' id: slider2 name: 'hop' step: 20 self.value_label.color: 1,1,1,0.15
But this doesn’t work.
Here is my minimal code as of now: .py:
from kivy.config import Config from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.uix.slider import Slider from kivy.app import App from kivy.properties import NumericProperty, StringProperty class MySlider(BoxLayout): name = StringProperty('Param') min = NumericProperty(0) max = NumericProperty(100) step = NumericProperty() def __init__(self, *args, **kwargs): super(MySlider, self).__init__(*args, **kwargs) self.value_label = Label() self.value_label.id = "value_label" self.slider = Slider() self.slider.bind(value=self._on_value) self.name_label = Label() self.value_label.text = str(self.slider.value) self.slider.orientation = 'vertical' self.add_widget(self.value_label) self.add_widget(self.slider) self.add_widget(self.name_label) def on_name(self, obj, val): self.name_label.text = val def on_min(self, obj, val): self.slider.min = val def on_max(self, obj, val): self.slider.max = val def on_step(self, obj, val): self.slider.step = val def _on_value(self, obj, val): self.value_label.text = str(self.slider.value) class MyLayout(BoxLayout): def __init__(self, **kwargs): super(MyLayout, self).__init__(**kwargs) class test7App(App): def build_config(self, config): Config.set('kivy', 'exit_on_escape', '0') Config.set('input', 'mouse', 'mouse,multitouch_on_demand') self.title = 'My Sliders' def build(self): return MyLayout() if __name__ == '__main__': test7App().run()
and the kv file:
#:kivy 2.0.0 <MyLayout>: orientation : 'horizontal' canvas: Color: rgba: 1,1,1,0.15 Rectangle: size: self.size pos: self.pos MySlider: orientation: 'vertical' id: slider1 name: "hip" min: -30 max: +60 step: 1 MySlider: orientation: 'vertical' id: slider2 name: 'hop' step: 20
If you have any suggestion about how to get there in the nicest (and economical) way, I would be grateful.
Thanks a lot. C
Advertisement
Answer
You can do that all from the kv
file. In fact, you don’t even need to define the MySlider
class in the python code. You can modify your kv
like this:
#:kivy 2.0.0 <MySlider@BoxLayout>: orientation: 'vertical' name: 'Param' min: 0 max: 100 step: 1 value_label_color: 1,1,1,0.15 Label: id: value_label text: str(slider.value) color: root.value_label_color Slider: id: slider orientation: root.orientation min: root.min max: root.max step: root.step Label: text: root.name <MyLayout>: orientation : 'horizontal' canvas: Color: rgba: 1,1,1,0.15 Rectangle: size: self.size pos: self.pos MySlider: orientation: 'vertical' id: slider1 name: "hip" min: -30 max: +60 step: 1 MySlider: orientation: 'horizontal' id: slider2 name: 'hop' step: 20
and your python code simplifies to:
from kivy.config import Config from kivy.lang import Builder from kivy.uix.boxlayout import BoxLayout from kivy.app import App class MyLayout(BoxLayout): def __init__(self, **kwargs): super(MyLayout, self).__init__(**kwargs) class test7App(App): def build_config(self, config): Config.set('kivy', 'exit_on_escape', '0') Config.set('input', 'mouse', 'mouse,multitouch_on_demand') self.title = 'My Sliders' def build(self): return MyLayout() if __name__ == '__main__': test7App().run()