1

假设我有一个 id:fruit 和值“apple”、“banana”、“watermelon”的微调器。

我有一些代码,例如:

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

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

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

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

2 回答 2

1

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

# -*- 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()
于 2016-03-28T14:59:09.973 回答
0

Spinner 值在 a 中ListProperty,因此您可以像这样对它们使用 enumerate:

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

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

于 2016-03-28T14:34:16.153 回答