我的基于Kivy的应用程序中有两个屏幕,每个屏幕都有一个RecycleView来显示列表。当我按下一个按钮时,两个RV都应该更新(add_button_clicked()
)在一个屏幕上。目前,第一个RV(AddRecipe屏幕)的工作原理与预期一致。然而,ViewList屏幕上的RV并没有用新数据更新。
我是Python的新手,甚至是Kivy的新手--我在这里遗漏了什么?
.py:
#! python3
# GroceryList.py
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.spinner import Spinner
from kivy.properties import ListProperty
from kivy.properties import ObjectProperty
from kivy.uix.recycleview import RecycleView
selectedMeals = []
ingredients = []
class ViewList(Screen):
def updateList(self, portions, recipe):
ingredients.append((portions, recipe))
print(ingredients) # This proves updateList is getting called
##THE FOLLOW RV THINGS DON'T WORK:
self.ids.shoplist.data = [{'text': '%s (%s)' %(ingredients[i][0], ingredients[i][1])}
for i in range(len(ingredients))]
self.ids.shoplist.refresh_from_data()
##
class AddRecipe(Screen):
recipes = ListProperty()
recipes = {'Guacarole':5, 'Salsa':3, 'Chips':1} # Sample dict for demo
def add_one(self):
if self.addportions.text != '':
value = int(self.addportions.text)
self.addportions.text = str(value+1)
def subtract_one(self):
if self.addportions.text != '':
value = int(self.addportions.text)
self.addportions.text = str(value-1)
def add_button_clicked(self, recipe, portions):
if recipe != '':
selectedMeals.append((recipe, portions))
self.ids.mealslist.data = [{'text': '%s (%s)' %(selectedMeals[i][0], selectedMeals[i][1])}
for i in range(len(selectedMeals))]
self.ids.mealslist.refresh_from_data()
ViewList().updateList(portions, recipe)
def spinner_clicked(self, val):
self.addportions.text = str(self.recipes[val])
class WindowManager(ScreenManager):
pass
class GroceryList(App):
mealsRVdata = ListProperty()
shoppingRVdata = ListProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.sm = ScreenManager()
def build(self):
Builder.load_file("grocerylist.kv")
screens = [ViewList(name='viewlist'), AddRecipe(name='addrecipe')]
for screen in screens:
self.sm.add_widget(screen)
self.sm.current = "addrecipe"
return self.sm
if __name__ == '__main__':
GroceryList().run()
和.kv:
#:kivy 1.11.1
# GroceryList.kv
# Used by GroceryList.py
WindowManager:
AddRecipe:
ViewList:
<ViewList>:
name: "viewlist"
shoplist: shoplist
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint: (1, 0.8)
RecycleView:
id: shoplist
data: app.shoppingRVdata
viewclass: 'RVLabel'
RecycleGridLayout:
cols: 1
size_hint: None, None
default_size: sp(200), sp(25)
height: self.minimum_height
width: self.minimum_width
BoxLayout:
size_hint: (1, 0.2)
Button:
text: "View shopping list"
on_release:
app.root.current = "viewlist"
Button:
text: "Add recipes"
on_release:
app.root.current = "addrecipe"
root.manager.transition.direction = "left"
<AddRecipe>:
name: "addrecipe"
addportions: addportions
mealslist: mealslist
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint: (1, 0.08)
Label:
size_hint: (0.64, 1)
font_size: 20
text: "Select a meal to add"
Label:
size_hint: (0.36, 1)
font_size: 20
text: "Select portions"
BoxLayout:
size_hint: (1, 0.08)
Spinner:
id: add_spinner
size_hint: (0.64, 1)
text: ""
values: root.recipes.keys()
on_text:
root.spinner_clicked(add_spinner.text)
Button:
size_hint: (0.12, 1)
font_size: 36
text: "-"
on_release: root.subtract_one()
Label:
id: addportions
size_hint: (0.12, 1)
font_size: 24
text: ''
Button:
size_hint: (0.12, 1)
font_size: 36
text: "+"
on_release: root.add_one()
FloatLayout:
size_hint: (1, 0.08)
Button:
size_hint: (0.4, 1)
pos_hint: {"x": 0.3, "top": 1}
text: "Add to shopping list"
on_release:
root.add_button_clicked(add_spinner.text, addportions.text)
BoxLayout:
size_hint: (1, 0.68)
RecycleView:
id: mealslist
data: app.mealsRVdata
viewclass: 'RVLabel'
RecycleGridLayout:
cols: 1
size_hint: None, None
default_size: sp(200), sp(25)
height: self.minimum_height
width: self.minimum_width
BoxLayout:
size_hint: (1, 0.08)
Button:
text: "View shopping list"
on_release:
app.root.current = "viewlist"
root.manager.transition.direction = "right"
Button:
text: "Add recipes"
on_release:
app.root.current = "addrecipe"
<RVLabel@Label>:
text_size: self.size
我在浏览其他问题时偶然发现了修复方法--更全面地指定RV。
App.get_running_app().root.get_screen('viewlist').ids.shoplist.data = ....
不过我打算把这个问题留着,因为现在我想知道为什么这个RV需要指定得这么完整,而AddRecipe界面的RV不需要。