Best practise: Variable gets changed by widget AND by the application

14 views
Skip to first unread message

Der Achim

unread,
Jun 20, 2018, 4:24:57 PM6/20/18
to Kivy users support
This is a how-to question: I have a variable that gets modified programmatically by the application. This variable also has a visible representation in the GUI as a slider. Here, the user may modify this variable as well by dragging the slider.

To be more specific:
1) If the user drags the slider to a new position, the variable should get a new value according to that position.
2) If the application modifies the variable, the slider should move to the corresponding position.

Thus, we have two-way correspondence here.
To my knowledge, this is not possible in Kivy: The sliders position may be bound to a variable. If the variable is changed, so does the slider's position.
But the other way round does not work: The slider does not update the variable.

Here is a summary what i did:
#!/usr/bin/env python
# -*- coding: latin-1 -*-
# (--> encoding for umlauts...)

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.slider import Slider
from kivy.uix.button import Button
from kivy.lang.builder import Builder
from kivy.properties import NumericProperty

Builder.load_string("""
<Slid>:    # GridLayout
    cols: 1
    Button:
        text: "
move to 3"
        on_release: root.move_to(3)
    Slider:
        min: 0.0
        max: 4.0
        step: 1.0
        value: root.slider_value
       
        on_value: root.slider_callback(self.value)
        orientation: "
horizontal"
"""
)

class Slid(GridLayout):
       
    slider_value
= NumericProperty(2)
   
   
def slider_callback(self, new_value):
       
print "=== slider is moving ==="
       
print "bound variable: {}".format(self.slider_value)
       
print "slider's value: {}".format(new_value)
   
   
def move_to(self, value):
       
print "=== moving slider to 3 ==="
       
self.slider_value = 3
       
class SlidApp(App):

   
def build(self):
        m
= Slid()
       
return m
   
if __name__ == '__main__':
   
SlidApp().run()

If you run this application the lower half of the screen will contain a slider. Hit the button in the top half. This sets the bound variable 'slider_value' to 3. The slider moves to position 3. This resembles case 1), where the variable is modified by the application. This works.

But if you move the slider, the variable 'slider_value' ist NOT updated.

One solution might be to install an 'on_value' callback that gets called when the slider is moved.
The callback then might set the variable 'slider_value' to the value of the slider. BUT: If 'slider_value' is modified, the slider moves, and the callback is called again! This is definitely not wanted.

Is there a way to install a two-way update?
Reply all
Reply to author
Forward
0 new messages