【问题标题】:Getting Index of Kivy Spinner获取 Kivy Spinner 的索引
【发布时间】:2016-03-28 14:22:40
【问题描述】:

假设我有一个 id:fruit 和值 "apple","banana","watermelon" 的微调器。

我有一些类似的代码:

if(self.ids['fruit'].text=='apple'):
   a=2

现在,在我的应用程序中,我有一个语言选择选项。因此,如果我选择“西班牙语”,我会将苹果更改为西班牙语,我上面的代码将失败(id 将仅保留为英文,因为我不会更改它)。但是所选值的索引将保持不变。

那么,kivy spinner 是否有索引支持,我的意思是:

if(self.ids['fruit'].id==1):
   a=2

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    为了将值(和当前选择)与显示的文本分开,我编写了Spinner 的子类。它将显示值 (values) 与值的逻辑表示 (hidden_values) 分开。此外,它还有一个额外的属性text_transformer,可以将selected_textvalues的当前项)和selected_valuehidden_values的当前项)转换为显示文本。该代码也包含一个示例。对于我的原始版本(带有原始示例),请查看this gist

    # -*- coding: utf-8 -*-
    
    import itertools
    from kivy.factory import Factory
    
    from kivy.compat import string_types
    from kivy.uix.spinner import Spinner, SpinnerOption
    from kivy.properties import ListProperty, ObjectProperty, StringProperty
    from kivy.logger import Logger
    
    class HVSpinnerOption(SpinnerOption):
        """Represents an option in HVSpinner. It adds :attr:`value` to represent a hidden value not shown to user."""
        value = ObjectProperty(None)
    
    class HVSpinner(Spinner):
        """Implements a spinner that keeps hidden values associated with
        options and displays a human readable text.
        """
    
        hidden_values = ListProperty()
        """Values associated with every item generated from :attr:`values`.
        :attr:`hidden_values`: is a :class:`~kivy.properties.ListProperty` and defaults to `range(len(self.values))`.
        The list may contain any kind of object.
        """
    
        selected_text = StringProperty()
        """Text representation of the selected item. By default, this is `None`. Upon selection of an item,
        it will be the corresponding element of :attr:`values`.
        """
    
        selected_value = ObjectProperty(None)
        """Representation of the selected item. Defaults to `None`. Upon selection of an item,
        it will be the corresponding element of :attr:`hidden_values`.
        """
    
        option_cls = ObjectProperty(HVSpinnerOption)
        '''Extension of class to display options. It must conform to requirements laid out for :attr:`~kivy.uix.spinner.option_cls`. In addition, the class must have a `value` property (should be :class:`~kivy.properties.ObjectProperty`).
    
        Additional :parameter:
        `text_transformer`: `None` or `callable`. Function that is used to set the :attr:`text` of :class:`HVSpinner` once
        an item has been selected. It should return a string and it should take 3 arguments:
    
        - :attr:`caller`: instance of :class:`HVSpinner` making the call
        - :attr:`text`: same as :attr:`selected_text`
        - :attr:`value`: same as :attr:`selected_value`
    
        Example::
    
            from kivy.base import runTouchApp
            from kivy.uix.gridlayout import GridLayout
            from kivy.uix.boxlayout import BoxLayout
            def print_current_val(obj, *largs):
                print "Spinner {} has text [{}], selected_text [{}] and hidden value [{}]".format(obj, obj.text, obj.selected_text, obj.selected_value)
    
            def transformator(caller, text, value):
                return "Now at >{}< ({})".format(text, value)
    
            vals = ["item {}".format(i) for i in range(8)]
            hvals  = ["<{}>".format(i + 17) for i in range(len(vals)) ]
            gl = GridLayout(rows=1)
    
            hvs1 = HVSpinner(values=vals, hidden_values=hvals, text='Select Me',
                 size_hint=(.3, None), height="30dp")
            hvs2 = HVSpinner(values=vals, text='No, Me', size_hint=(.3, None), height="40dp")
            hvs3 = HVSpinner(values=vals, hidden_values=range(len(vals)), text='Please, me!', size_hint=(.3, None), height="30dp",
                text_transformer=transformator)
            hvs1.bind(selected_value=print_current_val)
            hvs2.bind(selected_value=print_current_val)
            hvs3.bind(selected_value=print_current_val)
            gl.add_widget(hvs1)
            gl.add_widget(hvs2)
            gl.add_widget(hvs3)
            runTouchApp(gl)
    
        '''
    
        def __init__(self, *args, **kwargs):
            self.text_transformer = kwargs.pop('text_transformer', None)
            super(HVSpinner, self).__init__(*args, **kwargs)
    
        def _update_dropdown(self, *largs):
            dp = self._dropdown
            cls = self.option_cls
            if isinstance(cls, string_types):
                cls = Factory.get(cls)
            dp.clear_widgets()
            if len(self.hidden_values) == 0:
                self.hidden_values = range(len(self.values))
            if len(self.values) != len(self.hidden_values):
                Logger.warning("HVSpinner: 'values' and 'hidden_values' have different lengths.")
            for tv, hv in itertools.izip(self.values, self.hidden_values):
                item = cls(text=tv, value=hv)
                item.bind(on_release=lambda option: dp.select((option.text, option.value)))
                dp.add_widget(item)
    
        def _on_dropdown_select(self, instance, data, *largs):
            if callable(self.text_transformer):
                self.text = self.text_transformer(self, data[0], data[1])
            else:
                self.text = data[0]
            self.selected_text = data[0]
            self.selected_value = data[1]
            self.is_open = False
    
    Factory.register('HVSpinner', cls=HVSpinner)
    
    def main():
        from kivy.app import App
        from kivy.lang import Builder
        from kivy.clock import Clock
    
        kvstr = '''
    GridLayout:
        cols: 2
        HVSpinner:
            id: my_spinner
            text: "Pick one"
            values: ["apple", "banana", "watermelon"]
        Button:
            text: "Do something with it!"
            on_press: app.do_something()
        Label:
            text: "Current language: {}".format(app.current_language)
        Button:
            text: "Change Language"
            on_press: app.change_language()
    
        '''
    
    
        item_list = ["apple", "banana", "watermelon"]
        item_list_spanish = ["manzana", "banana", "sandía"]
    
    
        class AnApp(App):
            current_language = StringProperty('English')
            def build(self):
                Clock.schedule_once(self.set_up_spinner, 0)
                return Builder.load_string(kvstr)
            def change_language(self):
                if self.current_language == 'English':
                    self.current_language = 'Spanish'
                    self.root.ids.my_spinner.values = item_list_spanish
                else:
                    self.current_language = 'English'
                    self.root.ids.my_spinner.values = item_list
    
            def set_up_spinner(self, dt=0):
                def transformator(caller, text, value):
                    if self.current_language=='English':
                        return "You picked: {}".format(text)
                    else:
                        return "Escogió: {}".format(text)
                self.root.ids.my_spinner.text_transformer = transformator
            def do_something(self):
                if self.root.ids.my_spinner.selected_value == 0:
                    print "An apple was picked!"
    
        AnApp().run()
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    【解决方案2】:

    微调器值在ListProperty 中,因此您可以像这样对它们使用枚举:

    for index, text in enumerate(self.ids.fruit.values):
        if index == 1:
            a=2
    

    即使您不能在 ListProperty 上使用 enumerate,您仍然可以在函数开头从 values 创建自己的列表。当然枚举从零开始,所以如果你想在代码中使用1index + 1 是必要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 1970-01-01
      • 1970-01-01
      • 2017-01-28
      • 1970-01-01
      • 2016-03-29
      相关资源
      最近更新 更多