Reputation: 79
I am trying to do a very simple example in kivy (kv) as follows:
#:import Toolbar kivymd.toolbar.Toolbar
BoxLayout:
orientation: 'vertical'
Toolbar:
id: toolbar
title: 'My Toolbar'
md_bg_color: app.theme_cls.primary_color
background_palette: 'Primary'
background_hue: '500'
left_action_items: [['arrow-left', app.root.ids.scr_mngr.current = 'screen1' ]]
right_action_items: [['arrow-right', app.root.ids.scr_mngr.current = 'screen2' ]]
ScreenManager:
id: scr_mngr
Screen:
name: 'screen1'
Toolbar:
title: "Screen 1"
Screen:
name: 'screen2'
Toolbar:
title: "Screen 2"
This will fail because both left_action_items and right_action_items expect a list of pairs: [name_of_icon, expression]. On the other hand, when you deal with buttons, the statement would be legal for instance if we do something like:
on_release:
app.root.ids.scr_mngr.current = 'screen1'
On the other hand, the right approach for left_action_item would be something like:
left_action_items: [['arrow-left', lambda x: app.root.ids.scr_mngr.current = 'screen1' ]]
But this is not legal, because you cannot perform such assigment in lambda under python.
What would be right approach for left_action_items to change the screen?
Upvotes: 1
Views: 5655
Reputation: 505
This is the simplest way I have found to change the screen clicking on a MDToolbar icon:
main.py
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.lang import Builder
Builder.load_file("telas.kv")
class Tela1(Screen):
pass
class Tela2(Screen):
pass
class MainApp(MDApp):
def build(self):
self.sm = ScreenManager(transition=NoTransition())
self.sm.add_widget(Tela1(name="tela1"))
self.sm.add_widget(Tela2(name="tela2"))
return self.sm
def change_screen(self, tela):
self.sm.current = tela
if __name__ == "__main__":
MainApp().run()
telas.kv
<Tela1>:
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "My App"
MDRoundFlatButton:
text: "Go to Tela 2"
on_release: app.root.current = "tela2"
MDLabel:
text: "Tela 1"
<Tela2>:
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Tela 2"
left_action_items: [["arrow-left", lambda x: app.change_screen("tela1")]]
MDLabel:
text: "Tela 2"
Upvotes: 3
Reputation: 434
Also one more method. That I using:
left_action_items: [['arrow-left', lambda x: root.manager.change_screen("main_screen")]]
Realization of function change_screen() inside the screen manager:
def change_screen(self, screen):
# the same as in .kv: app.root.current = screen
self.current = screen
Upvotes: 2
Reputation: 1347
There are multiple options, you can do
left_action_items: [('arrow-left', (app.root.ids.scr_mngr, 'current', 'screen1'))]
and later do:
for icon, expr in self.left_action_items:
setattr(*expr)
If you really want an executable expression you can do:
left_action_items: [('arrow-left', lambda: setattr(app.root.ids.scr_mngr, 'current' 'screen1'))]
Upvotes: 2
Reputation: 5405
You could make your root class into a python class, and have a change_screen method there. Also make your screenmanager to an ObjectProperty in the root class.
Then use partial in kv to be able to pass arguments to the method.
Try like this:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivymd.theming import ThemeManager
class MyLayout(BoxLayout):
scr_mngr = ObjectProperty(None)
def change_screen(self, screen, *args):
self.scr_mngr.current = screen
KV = """
#:import Toolbar kivymd.toolbar.Toolbar
#:import partial functools.partial
MyLayout:
scr_mngr: scr_mngr
orientation: 'vertical'
Toolbar:
id: toolbar
title: 'My Toolbar'
left_action_items: [['arrow-left', partial(root.change_screen, 'screen1') ]]
right_action_items: [['arrow-right', partial(root.change_screen, 'screen2') ]]
ScreenManager:
id: scr_mngr
Screen:
name: 'screen1'
Toolbar:
title: "Screen 1"
Screen:
name: 'screen2'
Toolbar:
title: "Screen 2"
"""
class MyApp(App):
theme_cls = ThemeManager()
def build(self):
return Builder.load_string(KV)
MyApp().run()
Upvotes: 2