Kivy: RecycleView不更新

问题描述 投票:1回答:1

我的基于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
kivy kivy-language
1个回答
0
投票

我在浏览其他问题时偶然发现了修复方法--更全面地指定RV。

App.get_running_app().root.get_screen('viewlist').ids.shoplist.data = ....

不过我打算把这个问题留着,因为现在我想知道为什么这个RV需要指定得这么完整,而AddRecipe界面的RV不需要。

© www.soinside.com 2019 - 2024. All rights reserved.