如何从Kivy的Spinner获取变量并在RecycleView中使用?
问题分析与解决方案
你的核心问题在于:
- RecycleView的
data仅在初始化时加载一次,Spinner选择变化后不会自动更新 - Spinner的文本是大写,但
freezer函数的字典键是小写,存在大小写不匹配 - 未正确绑定Spinner的选择值到可监听的Kivy属性,导致无法联动更新RecycleView
修正步骤
1. 修正MyLayout的属性定义
将label_current定义为StringProperty,确保它是可监听的Kivy属性,而非普通变量:
class MyLayout(Widget): cheminImage = StringProperty('assets/32/type.png') value = StringProperty('viande') label_current = StringProperty("viande") # 新增可监听属性 def on_spinner_select(self, text): self.label_current = text.lower() # 转换为小写,匹配freezer的键 self.changeImage() self.ids.rv.update_data(self.label_current) # 触发RecycleView更新 def changeImage(self): img = 'assets/32/' + self.label_current + ".png" self.cheminImage = img
2. 给RecycleView添加id以便访问
在kv语言中为MyRecycleView添加id,方便从MyLayout中调用其方法:
<MyLayout>: # ... 其他代码 ... MyRecycleView: id: rv # 添加id用于后续访问
3. 修改RecycleView,添加更新数据的方法
让RecycleView可以接收外部参数,动态更新data:
class MyRecycleView(RecycleView): rvtest = StringProperty('type') def __init__(self, **kwargs): super(MyRecycleView, self).__init__(**kwargs) self.update_data("viande") # 初始化时加载默认数据 def update_data(self, type_aliment): # 根据传入的类型更新RecycleView数据 self.data = [{'text': str(x)} for x in freezer(type_aliment)]
4. 简化Spinner的on_text事件
合并Spinner的重复事件处理,避免逻辑分散:
Spinner: size_hint: 1, .1 id: spinner_id text: "Type" values: ["ACCOMPAGNEMENT", "AROMATIQUE", "DESSERT", "PLAT", "VIANDE", "POISSON", "SAUCE", "SOUPE"] on_text: root.on_spinner_select(self.text)
5. 处理大小写匹配
Spinner选项为大写,而freezer字典键为小写,通过text.lower()转换后再传入,避免KeyError。
完整修正后的代码
from kivy.app import App from kivy.properties import ObjectProperty, StringProperty, ListProperty from kivy.uix.boxlayout import BoxLayout from kivy.lang import Builder from kivy.uix.recycleview import RecycleView from kivy.uix.recycleview.views import RecycleDataViewBehavior from kivy.uix.widget import Widget from kivy.uix.image import Image from kivy.core.window import Window Builder.load_string(""" <MyRecycleView>: id: rv viewclass: 'Label' RecycleBoxLayout: default_size: None, dp(56) default_size_hint: 1, None size_hint_y: None height: self.minimum_height orientation: 'vertical' <MyLayout>: label_current: "type" BoxLayout: orientation: 'vertical' size: root.width, root.height Button: text: 'Ajouter/Supprimer/Modifier' size_hint: 1, .1 on_release: root.ajoutSuppMod() Spinner: size_hint: 1, .1 id: spinner_id text: "Type" values: ["ACCOMPAGNEMENT", "AROMATIQUE", "DESSERT", "PLAT", "VIANDE", "POISSON", "SAUCE", "SOUPE"] on_text: root.on_spinner_select(self.text) Label: id: click_label text: "CONGELO Liste" font_size: 32 size_hint: 1, .2 MyImage: id: img source: root.cheminImage MyRecycleView: id: rv """) def freezer(type_aliment): dict_freez = {"accompagnement": [1, 2], "aromatique": [3, 4], "dessert": [1, 2], "soupe": [5, 2], "plat": [1, 2], "poisson": [1, 2], "sauce": [1, 2], "viande": [1, 2], "divers": [1, 2]} return dict_freez[type_aliment] class MyImage(Image): pass class MyLayout(Widget): cheminImage = StringProperty('assets/32/type.png') value = StringProperty('viande') label_current = StringProperty("viande") def ajoutSuppMod(self): # 可在此添加按钮逻辑 pass def on_spinner_select(self, text): self.label_current = text.lower() self.changeImage() self.ids.rv.update_data(self.label_current) def changeImage(self): img = 'assets/32/' + self.label_current + ".png" self.cheminImage = img class MyViewClass(RecycleDataViewBehavior, BoxLayout): text = StringProperty("") index = None def refresh_view_attrs(self, rv, index, data): self.index = index return super(MyViewClass, self).refresh_view_attrs(rv, index, data) class MyRecycleView(RecycleView): rvtest = StringProperty('type') def __init__(self, **kwargs): super(MyRecycleView, self).__init__(**kwargs) self.update_data("viande") def update_data(self, type_aliment): self.data = [{'text': str(x)} for x in freezer(type_aliment)] class SpinApp(App): def build(self): Window.clearcolor = (0, 0, 0, 1) return MyLayout() if __name__ == '__main__': SpinApp().run()
关键说明
- Kivy的属性(如
StringProperty)自带监听机制,值变化时可触发关联操作,这是普通Python变量不具备的特性 - RecycleView的
data不会自动响应外部变量变化,需在Spinner选择时主动调用更新方法 - 务必注意字符串大小写匹配,避免字典查找时出现KeyError
内容的提问来源于stack exchange,提问作者Fabien Samson
相关产品推荐
相关产品推荐

