屏幕下 recycleview 数据的 kivy 问题
kivy issue with recycleview data when under screen
Kivy 新手,在通过屏幕使用 recycleView 时遇到问题。如果我将屏幕设置为以 self.manager = MainWidget() 开始进行测试,则数据加载正常,但是当将其正确设置为 ScreenManager() 时,self.recycleView 始终为 NoneType 并在我尝试设置时崩溃self.recycleView.数据。我假设这是某种参考问题,因为当我使用 on_parent 和 MainWidget 加载它时它有效
直接进入 MainWidget():
self.manager = MainWidget()
使用 MyScreenManager()
self.manager = MyScreenManager()
结果错误:
File "C:/path/to/main.py",
line 42, in on_parent
{"name": "name1"}, {"name": "name2"}, {"name": "name3"}, {"name": "name4"} AttributeError: 'NoneType' object has no attribute 'data'
Process finished with exit code 1
main.py
from kivy.app import App
from kivy.properties import StringProperty, NumericProperty, BooleanProperty, ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from navigation_screen_manager import NavigationScreenManager
class MyScreenManager(NavigationScreenManager):
pass
class MainMenu(BoxLayout):
pass
class ItemWidget(BoxLayout):
id = NumericProperty()
name = StringProperty()
links_to = StringProperty()
is_disabled = BooleanProperty()
description = StringProperty()
def get_menu(self, id):
if id == 9:
quit()
else:
print("you pressed" + str(id))
class MainWidget(FloatLayout):
recycleView = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
print('initialized')
self.items = ['item1', 'item2']
def on_parent(self, widget, parent):
print(f'parent of {self} is {self.parent}')
self.recycleView.data = [
{"name": "name1"}, {"name": "name2"}, {"name": "name3"}, {"name": "name4"}
]
class TheLabApp(App):
manager = ObjectProperty(None)
def build(self):
self.manager = MyScreenManager()
# return main interface
return self.manager
TheLabApp().run()
thelab.kv
#: import navigation_screen_manager navigation_screen_manager
#: import utils kivy.utils
#:set color1 "#DD7835"
#:set color2 "#D8D8D8"
<CoverImage@CoverBehavior+Image>:
reference_size: self.texture_size
<MyScreenManager>
Screen:
name: "MainWidget"
MainWidget:
<ItemWidget>:
BoxLayout:
size_hint_max_x: dp(300)
size_hint_min_x: dp(150)
orientation: "vertical"
Button:
text_size: self.size
background_color: 0,0,0,0
halign: "left"
valign: "center"
text: root.name
#on_press: quit() #root.get_menu(root.id)
BoxLayout:
spacing: dp(10)
FitLabel:
font_size: dp(22)
bold: True
LeftAlignLabel:
text: "description"
color: utils.get_color_from_hex(color2)
<MainWidget>:
recycleView: recycleView
CoverImage:
source: 'images/menu_background.jpg'
canvas:
Color:
rgba: 0, 0, 0, .6
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: "vertical"
Image:
source: 'images/small_logo.png'
allow_stretch: True
size_hint: None, None
size: dp(150), dp(60)
pos_hint: { "center_x": .5 }
TitleLabel:
text: "Title Label"
BoxLayout:
padding: dp(20), dp(20)
RecycleView:
id: recycleView
viewclass: 'ItemWidget'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
spacing: dp(16)
<FitLabel@Label>:
size_hint: None, None
size: self.texture_size
<TitleLabel@FitLabel>:
font_size: dp(22)
bold: True
padding: dp(16), dp(3)
canvas.before:
Color:
rgb: utils.get_color_from_hex(color1)
Rectangle:
pos: self.pos
size: self.size
<LeftAlignLabel@Label>
text_size: self.size
halign: "left"
valign: "center"
canvas.before:
Color:
#rgb: utils.get_random_color()
rgba: 0, 0, 0, 0
Rectangle:
pos: self.pos
size: self.size
navigation_screen_manager.py
from kivy.uix.screenmanager import ScreenManager
class NavigationScreenManager(ScreenManager):
screen_stack = []
def push(self, screen_name):
if screen_name not in self.screen_stack:
self.screen_stack.append(self.current)
self.transition.direction = 'left'
self.current = screen_name
def pop(self):
if len(self.screen_stack) > 0:
screen_name = self.screen_stack[-1]
self.transition.direction = 'right'
del self.screen_stack[-1]
self.current = screen_name
因为你的recycleView
是MainWidget
的Property
,你可以在设置recycleView
时触发设置数据,像这样:
class MainWidget(FloatLayout):
recycleView = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
print('initialized')
self.items = ['item1', 'item2']
def on_recycleView(self, widget, rv):
self.recycleView.data = [
{"name": "name1"}, {"name": "name2"}, {"name": "name3"}, {"name": "name4"}
]
Kivy 新手,在通过屏幕使用 recycleView 时遇到问题。如果我将屏幕设置为以 self.manager = MainWidget() 开始进行测试,则数据加载正常,但是当将其正确设置为 ScreenManager() 时,self.recycleView 始终为 NoneType 并在我尝试设置时崩溃self.recycleView.数据。我假设这是某种参考问题,因为当我使用 on_parent 和 MainWidget 加载它时它有效
直接进入 MainWidget():
self.manager = MainWidget()
使用 MyScreenManager()
self.manager = MyScreenManager()
结果错误:
File "C:/path/to/main.py", line 42, in on_parent {"name": "name1"}, {"name": "name2"}, {"name": "name3"}, {"name": "name4"} AttributeError: 'NoneType' object has no attribute 'data'
Process finished with exit code 1
main.py
from kivy.app import App
from kivy.properties import StringProperty, NumericProperty, BooleanProperty, ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from navigation_screen_manager import NavigationScreenManager
class MyScreenManager(NavigationScreenManager):
pass
class MainMenu(BoxLayout):
pass
class ItemWidget(BoxLayout):
id = NumericProperty()
name = StringProperty()
links_to = StringProperty()
is_disabled = BooleanProperty()
description = StringProperty()
def get_menu(self, id):
if id == 9:
quit()
else:
print("you pressed" + str(id))
class MainWidget(FloatLayout):
recycleView = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
print('initialized')
self.items = ['item1', 'item2']
def on_parent(self, widget, parent):
print(f'parent of {self} is {self.parent}')
self.recycleView.data = [
{"name": "name1"}, {"name": "name2"}, {"name": "name3"}, {"name": "name4"}
]
class TheLabApp(App):
manager = ObjectProperty(None)
def build(self):
self.manager = MyScreenManager()
# return main interface
return self.manager
TheLabApp().run()
thelab.kv
#: import navigation_screen_manager navigation_screen_manager
#: import utils kivy.utils
#:set color1 "#DD7835"
#:set color2 "#D8D8D8"
<CoverImage@CoverBehavior+Image>:
reference_size: self.texture_size
<MyScreenManager>
Screen:
name: "MainWidget"
MainWidget:
<ItemWidget>:
BoxLayout:
size_hint_max_x: dp(300)
size_hint_min_x: dp(150)
orientation: "vertical"
Button:
text_size: self.size
background_color: 0,0,0,0
halign: "left"
valign: "center"
text: root.name
#on_press: quit() #root.get_menu(root.id)
BoxLayout:
spacing: dp(10)
FitLabel:
font_size: dp(22)
bold: True
LeftAlignLabel:
text: "description"
color: utils.get_color_from_hex(color2)
<MainWidget>:
recycleView: recycleView
CoverImage:
source: 'images/menu_background.jpg'
canvas:
Color:
rgba: 0, 0, 0, .6
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: "vertical"
Image:
source: 'images/small_logo.png'
allow_stretch: True
size_hint: None, None
size: dp(150), dp(60)
pos_hint: { "center_x": .5 }
TitleLabel:
text: "Title Label"
BoxLayout:
padding: dp(20), dp(20)
RecycleView:
id: recycleView
viewclass: 'ItemWidget'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
spacing: dp(16)
<FitLabel@Label>:
size_hint: None, None
size: self.texture_size
<TitleLabel@FitLabel>:
font_size: dp(22)
bold: True
padding: dp(16), dp(3)
canvas.before:
Color:
rgb: utils.get_color_from_hex(color1)
Rectangle:
pos: self.pos
size: self.size
<LeftAlignLabel@Label>
text_size: self.size
halign: "left"
valign: "center"
canvas.before:
Color:
#rgb: utils.get_random_color()
rgba: 0, 0, 0, 0
Rectangle:
pos: self.pos
size: self.size
navigation_screen_manager.py
from kivy.uix.screenmanager import ScreenManager
class NavigationScreenManager(ScreenManager):
screen_stack = []
def push(self, screen_name):
if screen_name not in self.screen_stack:
self.screen_stack.append(self.current)
self.transition.direction = 'left'
self.current = screen_name
def pop(self):
if len(self.screen_stack) > 0:
screen_name = self.screen_stack[-1]
self.transition.direction = 'right'
del self.screen_stack[-1]
self.current = screen_name
因为你的recycleView
是MainWidget
的Property
,你可以在设置recycleView
时触发设置数据,像这样:
class MainWidget(FloatLayout):
recycleView = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
print('initialized')
self.items = ['item1', 'item2']
def on_recycleView(self, widget, rv):
self.recycleView.data = [
{"name": "name1"}, {"name": "name2"}, {"name": "name3"}, {"name": "name4"}
]