I've modified a Kivy RecycleView example and put it into a screen with menu, but now it's showing empty pages instead of data. I suspect the root have changed but I'm unable to connect the RecycleView to the correct source.
To be honest I think I've to work more on learning how to proper link between different objects.
My modified version that has the issue:
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()
Original working example:
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()
You can define the root
widget in several ways.
If you have the build
method in the App
's subclass and it returns some Widget
, it will be set as the root
widget. Or you can assign the root
to the kv-rule by loading it there etc.
In this case in your kv-rule you defined RecycleView
as the root
widget but you haven't used it in build
to set it as the root
.
Meanwhile you returned MainBox
from the method build
so it will be used as root
widget. Again you loaded the kv-rule there so the design etc. will be applied to this root widget.
Now in order to add RecycleView
to RVScreen
(as you mentioned in comment) and set MainBox
as root
widget (as you did already) you can modify your kvlang
as follows:
<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()