2016-03-28 17 views
1

Angenommen, ich habe einen Spinner mit ID: Obst und Werte "Apfel", "Banane", "Wassermelone".Index von Kivy Spinner

Ich habe einige Code wie:

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

Nun, ich in meiner App eine Sprachauswahlmöglichkeit haben. Also, wenn ich "Spanisch" wähle, werde ich Apple in die spanische Sprache ändern und mein oben beschriebener Code wird fehlschlagen (die ID wird nur in Englisch bleiben, da ich sie nicht ändern werde). Der Index des ausgewählten Wertes bleibt jedoch gleich.

So gibt es Index-Unterstützung für Kivy Spinner, ich meine so etwas wie:

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

Antwort

0

Um die Werte (und die aktuelle Auswahl) getrennt vom angezeigten Text zu halten, habe ich eine Unterklasse von Spinner geschrieben. Es trennt die Werte für die Anzeige (values) von der logischen Darstellung der Werte (hidden_values). Darüber hinaus verfügt es über ein zusätzliches Attribut text_transformer, das die selected_text (aktuelle Position values) und selected_value (aktuelle Position hidden_values) in einen Anzeigetext umwandeln kann. Der Code enthält auch ein Beispiel. Für meine Originalversion (mit Originalbeispielen), schauen Sie sich this gist an.

# -*- 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() 
+0

Ich schätze Ihre Mühe, aber ich bin immer noch nicht so gut bei Kivy, um es zu verstehen. :( –

+0

@ user3388005 Ich habe den Code geändert, um ein Beispiel zu geben, das dem entspricht, was Sie vielleicht tun möchten. – zeeMonkeez

0

Spinner Werte sind in einem ListProperty, daher können Sie auf sie wie folgt aufzählen verwenden:

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

Selbst wenn Sie in ListProperty kein Enumerate verwenden können, können Sie am Anfang Ihrer Funktion trotzdem eine eigene Liste von values erstellen. Natürlich beginnt Enumerate von Null, so dass index + 1 erforderlich wäre, wenn Sie 1 in Ihrem Code verwenden möchten.