I'm trying to make this app which has multiple screens. I was creating the screenmanager in my .py file and everything was working as expected but i figured that i need to write the screenmanager in my .kv file. But it's just not working. I get this error kivy.factory.FactoryException: Unknown class <Home>
My home class is properly defined in my .kv file so i have no clue about why this is happening. i'm guessing that maybe i need to define the current screen somehow but idk how to. only the screenmanager and home class is worth looking at i think. Any help or guidance is appreciated.
this is my kv file
#:import dp kivy.metrics.dp
#:import ScreenManager kivy.uix.screenmanager.ScreenManager
#:import Screen kivy.uix.screenmanager.ScreenManager
#:set navbar_button_color (59/255, 68/255, 75/255, 1)
ScreenManager:
id: screen_manager
Home:
id: home
name: "home_screen"
manager: "screen_manager"
Daily:
id: daily
name: "daily_screen"
manager: "screen_manager"
Weekly:
id: weekly
name: "weekly_screen"
manager: "screen_manager"
Monthly:
id: monthly
name: "monthly_screen"
manager: "screen_manager"
Yearly:
id: yearly
name: "yearly_screen"
manager: "screen_manager"
<MyLayout>:
my_grid: my_grid
expense_button: expense_button
orientation: "vertical"
BoxLayout:
size_hint: 1,0.1
Button:
text: "Back"
size_hint: 0.1,1
# on_press:
# app.root.manager.current = "home_screen"
# app.root.manager.transition.direction = "right"
Button:
text: "Home"
size_hint: 0.1,1
Button:
text: "Daily"
size_hint: 0.1,1
Button:
text: "Weekly"
size_hint: 0.1,1
Button:
text: "Monthly"
size_hint: 0.1,1
Button:
text: "Load"
size_hint: 0.1,1
on_press: my_grid.load()
Button:
text: "Save"
size_hint: 0.1,1
on_press: my_grid.save()
Label:
text: dt.today().strftime("%d %B %Y")
size_hint: 0.3,1
canvas.before:
Color:
rgb: 59/255, 78/255, 85/255,1
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint: 1,0.15
Button:
text: "EXPENSES"
Button:
text: "REVENUE"
HeaderBox:
MyScroll:
MyGrid:
id: my_grid
size_hint: 1, None
height: self.minimum_height
BoxLayout:
orientation:"horizontal"
size_hint: 1,0.2
BoxLayout:
orientation: "vertical"
Button:
id: expense_button
text: "Expense Total:"
font_size: dp(20)
on_press:
self.text = "Expense Total: " + str(my_grid.expense_total)
revenue_button.text = "Revenue Total: " + str(my_grid.revenue_total)
profit_button.text = "Profit: " + str(my_grid.profit)
Button:
id: revenue_button
text: "Revenue Total: "
font_size: dp(20)
on_press:
expense_button.text = "Expense Total: " + str(my_grid.expense_total)
self.text = "Revenue Total: " + str(my_grid.revenue_total)
profit_button.text = "Profit: " + str(my_grid.profit)
Button:
id: profit_button
text: "Profit:"
font_size: dp(40)
on_press:
expense_button.text = "Expense Total: " + str(my_grid.expense_total)
revenue_button.text = "Revenue Total: " + str(my_grid.revenue_total)
self.text = "Profit: " + str(my_grid.profit)
<Home>:
BoxLayout:
orientation: "horizontal"
BoxLayout:
orientation: "vertical"
size_hint: 0.65, 1
spacing: 5
padding: 5
Button:
text: "Daily"
font_size: 40
size_hint: 1, 0.75
background_color: 59/255, 68/255, 75/255, 1
on_press:
root.manager.current = "daily_screen"
root.manager.transition.direction = "left"
root.manager.transition.duration = 0.8
Button:
text: "Yearly"
font_size: 40
size_hint: 1, 0.25
background_color: 101/255, 115/255, 131/255, 1
BoxLayout:
orientation: "vertical"
size_hint: 0.35,1
spacing: 5
padding: [0,5,5,5]
Button:
text: "Weekly"
font_size: 40
size_hint: 1, 0.50
background_color: 84/255, 98/255, 111/255, 1
Button:
text: "Monthly"
font_size: 40
size_hint: 1, 0.50
background_color: 152/255, 175/255, 199/255, 1
<Daily>:
MyLayout:
<Weekly>:
Label:
text:"Weekly"
<Monthly>:
Label:
text:"Monthly"
<Yearly>: ```
#for @ApuCoder #i saw a similar question and changed the return statement of my App class. now it throws a different error. Also i don't think the home class is causing the issue, coz i removed that class n then it said the next class was undefined. so it's something else. Anyway, i have a new error to deal with now.
root.manager.current = "daily_screen" AttributeError: 'str' object has no attribute 'current'```
class Home(Screen):
pass
class MyApp(App):
def build(self):
return Builder.load_file("sample1.kv")
if __name__ == "__main__":
MyApp().run()
There are some issues with your code, let's try to address those one by one.
1. In kvlang
you either design a predefined class from .py
or a class defined within itself. Thus either you'll do in .py
class MyButton(Button):
# Some prop. and/or methods if needed.
# Otherwise,
pass
Then in kvlang
for this class,
<MyButton>:
# Whatever you want...
Or equivalently you can define and design that class (dynamic class ) in kvlang
as,
<MyButton@Button>:
# Here is your design rule.
Now without inheriting a new class (not a default one) from a Widget
(or to be precise from EventDispatcher
) if you try to design it within kvlang
a FactoryException
will be raised.
2. The Screen
widgets has a read-only property manager
that is essentially a ScreenManager
widget. Thus when you do something like this,
ScreenManager:
id: screen_manager
Home:
id: home
name: "home_screen"
manager: "screen_manager"
i.e. assigning a string to it, you just overwrite its default manager by a string, that's why you got the error message AttributeError: 'str' object has no attribute 'current'
when you tried something like this
root.manager.current = "daily_screen"
from that screen.
What you need to do is,
ScreenManager:
id: screen_manager # Pass this id to the screen.
Home:
id: home
name: "home_screen"
manager: screen_manager # Although its not necessary to pass it over.
Also I think you can't assign it in python as it is a read-only property. In kvlang
, perhaps this is different.