I am writing a kivy program to populate news articles from stored json to kivy app. In kivy file: HomePage has box layout with id and I am trying to populate the same with python file using ids. ids is not working. I tried printing ids dictionary and the same, is printed blank. Code is as below :
import json
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from components.news_scroll import NewsScroll
Builder.load_file('main.kv')
class HomePage(Screen):
def on_enter(self):
self.list_news()
def list_news(self):
with open('news2023-07-15.json') as user_file:
parsed_json = json.load(user_file)
for result in parsed_json['results']:
self.ids._news.add_widget(NewsScroll(
news_title=result['title'],
news_content=result['content']
))
class RootWidget(ScreenManager):
pass
class MainApp(MDApp):
def build(self):
return RootWidget()
MainApp().run()
Kivy file is as below:
#: import NewsScroll components.news_scroll.NewsScroll
<RootWidget>:
HomePage:
<HomePage>:
BoxLayout:
orientation: 'vertical'
id: _news
I am getting this error:
Traceback (most recent call last):
File "kivy/properties.pyx", line 961, in kivy.properties.ObservableDict.__getattr__
KeyError: '_news'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/main.py", line 37, in <module>
MainApp().run()
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/app.py", line 955, in run
self._run_prepare()
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/app.py", line 925, in _run_prepare
root = self.build()
^^^^^^^^^^^^
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/main.py", line 34, in build
return RootWidget()
^^^^^^^^^^^^
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/uix/screenmanager.py", line 973, in __init__
super(ScreenManager, self).__init__(**kwargs)
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/uix/floatlayout.py", line 65, in __init__
super(FloatLayout, self).__init__(**kwargs)
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/uix/layout.py", line 76, in __init__
super(Layout, self).__init__(**kwargs)
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/uix/widget.py", line 366, in __init__
self.apply_class_lang_rules(
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/uix/widget.py", line 470, in apply_class_lang_rules
Builder.apply(
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/lang/builder.py", line 540, in apply
self._apply_rule(
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/lang/builder.py", line 659, in _apply_rule
widget.add_widget(child)
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/uix/screenmanager.py", line 1001, in add_widget
self.current = widget.name
^^^^^^^^^^^^
File "kivy/properties.pyx", line 520, in kivy.properties.Property.__set__
File "kivy/properties.pyx", line 567, in kivy.properties.Property.set
File "kivy/properties.pyx", line 606, in kivy.properties.Property._dispatch
File "kivy/_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
File "kivy/_event.pyx", line 1213, in kivy._event.EventObservers._dispatch
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/venv/lib/python3.11/site-packages/kivy/uix/screenmanager.py", line 1069, in on_current
screen.dispatch('on_enter')
File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/main.py", line 15, in on_enter
self.list_news()
File "/Users/pradnyanandmanoharjadhav/PycharmProjects/pythonProject/main.py", line 22, in list_news
self.ids._news.add_widget(NewsScroll(
^^^^^^^^^^^^^^
File "kivy/properties.pyx", line 964, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'. Did you mean: '__setattr__'?
I tried multiple things but I failed at everything. If you have some solution, kindly assist.
I tried init function. Error stays the same.
The problem is that the ids
of the HomePage
are not yet filled in when the on_enter()
method is triggered. A fix is to just delay the call to list_news()
slightly, until the ids
dictionary is complete. You can do this by using Clock.schedule_once()
like this:
def on_enter(self):
# self.list_news()
Clock.schedule_once(self.list_news)
This requires a small change in the list_news()
signature:
def list_news(self, *args):
This accounts for the dt
argument that Clock.schedule_once()
adds to the call.