Kivy RecycleView 进入屏幕后不显示数据

Kivy RecycleView not showing data after moving into a screen

我修改了一个 Kivy RecycleView 示例并将其放入带有菜单的屏幕中,但现在它显示的是空页面而不是数据。我怀疑根已更改,但我无法将 RecycleView 连接到正确的源。

老实说,我认为我必须更多地学习如何在不同对象之间正确 link。

我修改后的版本有问题:

from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty, NumericProperty, ListProperty
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder

from kivy.uix.screenmanager import Screen, ScreenManager

KV = """

<SomeMenu_ActionBar@ActionBar>:

    ActionView:
        id: ActionView
        HiddenIcon_ActionPrevious:
        ActionButton:
            text: 'Stop'
            on_release:  app.stop()
       
       
<HiddenIcon_ActionPrevious@ActionPrevious>:

    
<MainBox>:
    orientation: 'vertical'
    canvas.before:
        Color:
            rgb: .6, .6, .6
        Rectangle:
            pos: self.pos
            size: self.size
            # source: 'data/background.png'

    MyManager:
        id: sm
        RVScreen:
            id: rvscreen

    SomeMenu_ActionBar:
        id: ActionBar


<RecycleItem>:
    orientation: 'horizontal'
    Label:
        text: root.label_text
    TextInput:
        text: root.input_text
        on_text: root.set_text(self.text)

RecycleView:
    data: app.data
    viewclass: 'RecycleItem'
    RecycleBoxLayout:
        spacing: 10
        default_size: None, dp(80)
        default_size_hint: 1, None
        orientation: 'vertical'
        size_hint_y: None
        height: self.minimum_height


<RVScreen>:
    id: "rvscreen"
    BoxLayout:
        orientation: "vertical"
        RecycleView:
        Button:
            text: 'Previous screen'
            size_hint: None, None
            size: 150, 50
            on_release: root.manager.current = root.manager.previous()
"""

class RecycleItem(RecycleDataViewBehavior, BoxLayout):
    owner = ObjectProperty()
    index = NumericProperty(0)
    input_text = StringProperty()
    label_text = StringProperty()

    def set_text(self, text):
        if self.owner is not None:
            self.owner.data[self.index]['input_text'] = text
    
    def refresh_view_attrs(self, rv, index, data):
        self.index = index
        return super(RecycleItem, self).refresh_view_attrs(rv, index, data)

class MainBox(BoxLayout):
    """Mainbox under MainApp
    It contains the ScreenManager
    """
    pass

class RVScreen(Screen):
    pass

class MyManager(ScreenManager):
    """The screen manager that handles app screens
    """
    pass

class Test(App):
    data = ListProperty()

    def build(self):
        self.data = [{'label_text': "Label "+str(x), "input_text": "Input "+str(x), 'owner': self} for x in range(20)]
        Builder.load_string(KV)
        return MainBox()

Test().run()

原始工作示例:

from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty, NumericProperty, ListProperty
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder

KV = """
<RecycleItem>:
    orientation: 'horizontal'
    Label:
        text: root.label_text
    TextInput:
        text: root.input_text
        on_text: root.set_text(self.text)

RecycleView:
    data: app.data
    viewclass: 'RecycleItem'
    RecycleBoxLayout:
        spacing: 10
        default_size: None, dp(80)
        default_size_hint: 1, None
        orientation: 'vertical'
        size_hint_y: None
        height: self.minimum_height


<RVScreen>:
    BoxLayout:
        orientation: "vertical"
        RecycleView:
        Button:
            text: 'Previous screen'
            size_hint: None, None
            size: 150, 50
            on_release: root.manager.current = root.manager.previous()
"""

class RecycleItem(RecycleDataViewBehavior, BoxLayout):
    owner = ObjectProperty()
    index = NumericProperty(0)
    input_text = StringProperty()
    label_text = StringProperty()

    def set_text(self, text):
        if self.owner is not None:
            self.owner.data[self.index]['input_text'] = text
    
    def refresh_view_attrs(self, rv, index, data):
        self.index = index
        return super(RecycleItem, self).refresh_view_attrs(rv, index, data)

class Test(App):
    data = ListProperty()

    def build(self):
        self.data = [{'label_text': "Label "+str(x), "input_text": "Input "+str(x), 'owner': self} for x in range(20)]
        return Builder.load_string(KV)

Test().run()

您可以通过多种方式定义 root 小部件。

如果您有 build method in the App's subclass and it returns some Widget, it will be set as the root 小部件。或者您可以通过将 root 加载到 kv-rule 等

在这种情况下,在您的 kv-rule 中,您将 RecycleView 定义为 root 小部件,但您没有在 build 中使用它来将其设置为 root.

与此同时,您从方法 build 返回了 MainBox,因此它将用作 root 小部件。您再次在此处加载了 kv-rule,因此设计等将应用于此根小部件。

现在为了将 RecycleView 添加到 RVScreen(如您在 中提到的)并将 MainBox 设置为 root 小部件(如您所做的已经)你可以修改你的 kvlang 如下:

<SomeMenu_ActionBar@ActionBar>:

    ActionView:
        id: ActionView
        HiddenIcon_ActionPrevious:
        ActionButton:
            text: 'Stop'
            on_release:  app.stop()
       
       
<HiddenIcon_ActionPrevious@ActionPrevious>:

    
<MainBox>:
    orientation: 'vertical'
    canvas.before:
        Color:
            rgb: .6, .6, .6
        Rectangle:
            pos: self.pos
            size: self.size
            # source: 'data/background.png'

    MyManager:
        id: sm
        RVScreen:
            id: rvscreen

    SomeMenu_ActionBar:
        id: ActionBar


<RecycleItem>:
    orientation: 'horizontal'
    Label:
        text: root.label_text
    TextInput:
        text: root.input_text
        on_text: root.set_text(self.text)


<RVScreen>:
    id: "rvscreen"
    BoxLayout:
        orientation: "vertical"
        RecycleView:
            data: app.data
            viewclass: 'RecycleItem'
            RecycleBoxLayout:
                spacing: 10
                default_size: None, dp(80)
                default_size_hint: 1, None
                orientation: 'vertical'
                size_hint_y: None
                height: self.minimum_height
        Button:
            text: 'Previous screen'
            size_hint: None, None
            size: 150, 50
            on_release: root.manager.current = root.manager.previous()