首页 > 解决方案 > Kivy:制作包含不同小部件并能够在 kv 文件中访问它们的属性的单个小部件的最佳方法

问题描述

我正在尝试创建一个作为 Slider + 2 Labels 的类,一个显示滑块值的标签,一个显示滑块名称的标签。目标是在方便时重用它来代替 Slider。

我最终在我的类 MySlider 中创建属性,这些属性反映了我对 Slider 感兴趣的那些。例如,如果我希望能够指定值标签的颜色,我也可以这样做,将属性“value_label_color”添加到 MySlider 并在 on_value_label_color() 中设置标签的颜色...然后在 kv文件我会做这样的事情:

value_label_color: 1,0,1,0.15

如果我的 MySlider 类中有很多小部件,这会起作用,但可能会很长。

我认为可能有一种方法可以避免所有这些并直接从 kv 文件中访问标签的颜色,所以我可以执行以下操作?

    MySlider:
        orientation: 'vertical'
        id: slider2
        name: 'hop'
        step: 20
        self.value_label.color: 1,1,1,0.15

但这不起作用。

这是我现在的最小代码:.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()

和 kv 文件:

#: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

如果您对如何以最好(和经济)的方式到达那里有任何建议,我将不胜感激。

非常感谢。C

标签: pythonkivykivy-languageencapsulation

解决方案


kv您可以从文件中完成所有这些操作。事实上,你甚至不需要MySlider在 python 代码中定义类。你可以kv像这样修改你的:

#: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

并且您的 python 代码简化为:

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()

推荐阅读