ForyszeP
ForyszeP

Reputation: 163

Kivy. Switching screens with buttons not defined in the Screen

I've got a bit of a problem with my app. Below you will find much sipmlified and working code. The problem is that when I change screens that way the methods used for textinputs or buttons are called as many times as that class is used. Is it possible to switch between Screens using Button not defined in Screen like in <List_or_NotesScreen>?

from kivy.config import Config
Config.set('graphics', 'multisamples', '0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen

kv = """
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
#:import hex kivy.utils.get_color_from_hex
#:import Factory kivy.factory.Factory


ScreenManager:
    ListScreen:
    NotesScreen:

<ScreenSwitch>

    orientation: 'horizontal'
    size_hint_y: None
    height: 30
    Button:
        text: 'List'
        on_press: app.root.current = 'ListScreen'
    Button:
        text: 'Notes'
        on_press: app.root.current = 'NotesScreen'

<List>:
    orientation: 'vertical'
    Label:
        text: '1st'
    Label:
        text: '2nd'
    Label:
        text: '3rd'
<Notes>:
    TextInput:

<ListScreen>:
    name: 'ListScreen'
    BoxLayout:
        orientation: 'vertical'
        ScreenSwitch:
        List:

<NotesScreen>:
    name: 'NotesScreen'
    BoxLayout:
        orientation: 'vertical'
        ScreenSwitch:
        Notes:


"""

class ScreenSwitch(BoxLayout):
    pass

class List(BoxLayout):
    pass

class Notes(BoxLayout):
    pass

class NotesScreen(Screen):
    pass

class ListScreen(Screen):
    pass



sm = Builder.load_string(kv)

class TestApp(App):
    def build(self):
        return sm

if __name__ == '__main__':
    TestApp().run()

I need something like that but would like to avoid creating buttons in <List_or_Notes>

<List_or_NotesScreen>:

BoxLayout:
    orientation: 'vertical'
    ScreenSwitch:
    ScreenManager:
        id: list_or_notes
        Screen:
            name: 'Notes'
            Notes:
        Screen:
            name: 'List'
            List:
'''

Upvotes: 0

Views: 96

Answers (2)

ForyszeP
ForyszeP

Reputation: 163

If someone is interested I think below code is a solution:

from kivy.config import Config
Config.set('graphics', 'multisamples', '0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen

kv = """
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
#:import hex kivy.utils.get_color_from_hex
#:import Factory kivy.factory.Factory


ScreenManager:
    List_or_NotesScreen:

<ScreenSwitch>

    orientation: 'horizontal'
    size_hint_y: None
    height: 30
    Button:
        text: 'List'
        on_press: app.get_running_app().root.get_screen('List_or_NotesScreen').ids.list_or_notes.current = 'List'
    Button:
        text: 'Notes'
        on_press: app.get_running_app().root.get_screen('List_or_NotesScreen').ids.list_or_notes.current = 'Notes'

<List>:
    orientation: 'vertical'
    Label:
        text: '1st'
    Label:
        text: '2nd'
    Label:
        text: '3rd'
<Notes>:
    TextInput:

<List_or_NotesScreen>:
    name: 'List_or_NotesScreen'
    BoxLayout:
        orientation: 'vertical'
        ScreenSwitch:
        ScreenManager:
            id: list_or_notes
            Screen:
                name: 'Notes'
                Notes:
            Screen:
                name: 'List'
                List:


"""

class ScreenSwitch(BoxLayout):
    pass

class List(BoxLayout):
    pass

class Notes(BoxLayout):
    pass



class List_or_NotesScreen(Screen):
    pass



sm = Builder.load_string(kv)

class TestApp(App):
    def build(self):
        return sm

if __name__ == '__main__':
    TestApp().run()

Upvotes: 0

noEmbryo
noEmbryo

Reputation: 2231

You can do it by puting the ScreenManager inside the same BoxLayout as the buttons.
Check the comments..

from kivy.config import Config

Config.set('graphics', 'multisamples', '0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen

kv = """
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
#:import hex kivy.utils.get_color_from_hex
#:import Factory kivy.factory.Factory

# ScreenManager:  # don't need this here
#     ListScreen:
#     NotesScreen:

ScreenSwitch:  # make this the root widget
    orientation: 'vertical'
    BoxLayout:
        orientation: 'horizontal'
        size_hint_y: None
        height: 30
        Button:
            text: 'List'
            on_press: screen_man.current = 'ListScreen'
        Button:
            text: 'Notes'
            on_press: screen_man.current = 'NotesScreen'
    ScreenManager:  # add the Screens here
        id: screen_man  # you need this to change screens with buttons
        ListScreen:
        NotesScreen:

<ListA>:
    orientation: 'vertical'
    Label:
        text: '1st'
    Label:
        text: '2nd'
    Label:
        text: '3rd'

<Notes>:
    TextInput:

<ListScreen>:
    name: 'ListScreen'
    BoxLayout:
        orientation: 'vertical'
        # ScreenSwitch:  # remove from here
        ListA:

<NotesScreen>:
    name: 'NotesScreen'
    BoxLayout:
        orientation: 'vertical'
        # ScreenSwitch:  # remove from here
        Notes:
"""


class ScreenSwitch(BoxLayout):
    pass


class ListA(BoxLayout):
    pass


class Notes(BoxLayout):
    pass


class NotesScreen(Screen):
    pass


class ListScreen(Screen):
    pass


sm = Builder.load_string(kv)


class TestApp(App):
    def build(self):
        return sm


if __name__ == '__main__':
    TestApp().run()

Upvotes: 1

Related Questions