Kivy: RecycleView не обновляется - PullRequest
       4

Kivy: RecycleView не обновляется

1 голос
/ 22 апреля 2020

В моем приложении на Kivy есть два экрана, каждый с RecycleView для отображения списков. Оба RV должны обновляться, когда я нажимаю кнопку (add_button_clicked()) на одном экране. В настоящее время первый RV (экран AddRecipe) работает в основном так, как задумано. Однако RV на экране ViewList не обновляется новыми данными.

Я новичок в 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()

А .кв:

#: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

1 Ответ

0 голосов
/ 22 апреля 2020

Я наткнулся на исправление, просматривая другие вопросы - укажите RV более полно:

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

Я собираюсь оставить вопрос, хотя, потому что теперь я хочу чтобы знать, почему этот RV нужно указывать так полно, а тот, что на экране AddRecipe - нет.

...