如何用kv语言绑定属性?

时间:2017-12-31 13:39:21

标签: python data-binding kivy

此代码旨在显示两个kivy滑块。第二个滑块应与第一个滑块一起移动(但不是相反)。我已经完成绑定的课程DoubleSlider

import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout

kivy.require('1.10.0')

Builder.load_string ("""
<Slider>
    size_hint: 1, None
    height: dp(40)

<DoubleSlider@BoxLayout>:
    slider_1: slider_1
    slider_2: slider_2
    orientation: 'vertical'

    Slider
        id: slider_1

    Slider
        id: slider_2
        value: slider_1.value

<UI>:
    orientation: 'vertical'
    DoubleSlider:        
""")


class UI(BoxLayout):
    pass


class MyApp(App):
    def build(self):
        return UI()


if __name__ == '__main__':
    MyApp().run()

这是我发现的唯一解决方案(在kvlang中)。但是我无法使用它,所显示的绑定只是一个样本。

实际上我希望能够在具有数字属性的其他其他对象中使用第一个滑块的位置(具体不是同一个DoubleSlider对象的第二个滑块),这意味着我会做<UI>规则中的个案绑定。所以我删除了行value: slider_1.value并试图像这样修改<UI>规则:

<UI>:
    DoubleSlider:
        # Is expected to be equivalent, but doesn't work
        slider_2.value: slider_1.value

我还尝试使用getter('value')setter('value')无效。

问题

  • 在分配期间,我在<UI>做了什么? (我担心我没有绑定任何内容,但我只是重新分配slider_2属性,因为slider_2本身就是一个属性,而不是常规引用)

  • <UI>中绑定滑块的正确方法是什么? (最好只使用kv lang,除非这是不可能的)

2 个答案:

答案 0 :(得分:1)

如果要在实例化期间修改绑定,我不知道它是否是最佳选项,但您可以使用自定义属性。这也允许您在需要时解除绑定:

import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout

kivy.require('1.10.0')

Builder.load_string ("""
<Slider>
    size_hint: 1, None
    height: dp(40)

<DoubleSlider@BoxLayout>:
    tied: False                 # <<<<<<<<<<
    slider_1: slider_1
    slider_2: slider_2
    orientation: 'vertical'

    Slider
        id: slider_1

    Slider
        id: slider_2
        value: slider_1.value if root.tied else self.value


<UI>:
    orientation: 'vertical'
    BoxLayout:
        Label:
            text: "Tied"
        CheckBox:
            on_active: ds.tied = not ds.tied

    DoubleSlider:       
        id: ds
""")


class UI(BoxLayout):
    pass


class MyApp(App):
    def build(self):
        return UI()


if __name__ == '__main__':
    MyApp().run()

enter image description here

修改

另一种选择是创建一个与滑块的value属性关联的新属性,并使用on_语法:

import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout

kivy.require('1.10.0')

Builder.load_string ("""
<Slider>
    size_hint: 1, None
    height: dp(40)

<DoubleSlider@BoxLayout>:
    slider_1: slider_1
    slider_2: slider_2
    value1: slider_1.value
    value2: slider_2.value
    orientation: 'vertical'

    Slider
        id: slider_1

    Slider
        id: slider_2



<UI>:
    orientation: 'vertical'

    DoubleSlider:
        on_value1: self.slider_2.value = self.value1

""")


class UI(BoxLayout):
    pass


class MyApp(App):
    def build(self):
        return UI()


if __name__ == '__main__':
    MyApp().run()

答案 1 :(得分:1)

  

首先,我不确定绑定是否正确完成

您已正确完成绑定。使用kvlang有什么好处:它允许以声明式样式绑定属性。

在kv文件中绑定:

value: slider_1.value

在纯Python中也是如此:

slider_1.bind(value=slider_2.setter('value'))
  

所以我只需要在实例级别绑定属性。

您实际上在实例级别绑定了一些东西:在kvlang中设置Slider内的<DoubleSlider@BoxLayout>属性 - 与DoubleSlider实例的构造函数中的绑定滑块值相同在Python中。

如果根据不同DoubleSlider实例的条件需要不同的绑定,我恐怕你应该使用Python来实现它。