How do I change screenmanager screens from a button class?

17 views
Skip to first unread message

Edward Anderson

unread,
May 4, 2026, 11:57:06 AM (10 days ago) May 4
to Kivy users support
I am attempting to transfer between screenmanager screens using a button selected from a class of buttons.  The attached files are organized so that Main.py sets up the screens & screenmanager, Directory.py generates 60 buttons in the BtnStack class which transfer to the solveproblrm screen when one is selected and pressed, and the main.kv file formats everything.   I have tried many approaches (some of which are commented out) all of which failed. Significant lines of code are commented where I believe the problem lies.  I believe the problem is where to route the "manager.current = 'solveproblem'" too instead the usual "root". When testing, select one of the "1. xx" problems as the others have errors that I am presently addressing. I appreciate any and all help. TIA 
Main.py
Directory.py
SolveProblem.py
main.kv

ElliotG

unread,
May 4, 2026, 2:42:58 PM (10 days ago) May 4
to Kivy users support
I assume that from the BtnStack class in Directory.py, you want to access the ScreenManager class from the dynamically created buttons.  There are a number of ways to do this.
Perhaps the most straight forward is to access the App instance and use that to access the ScreenManager.  Here is a simplified example below.  Notice that in the ButtonScreen.first_screen method, App.get_running_app is used to access the App instance, and from that app instance, the root widget can be accessed. 

Hope this helps. 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button

kv = """
<LabelScreen@Screen>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: root.name
        Button:
            text: 'Next'
            size_hint_y: None
            height: dp(48)
            on_release: root.manager.current = root.manager.next()
           
<ButtonScreen>:
    GridLayout:
        id: grid_layout
        rows: 5
       
ScreenManager:      # this is the root widget
    LabelScreen:
        name: 'One'
    LabelScreen:
        name: 'Two'
    ButtonScreen:
        name: 'Three'
"""

class ButtonScreen(Screen):
    def on_kv_post(self, base_widget):   # executes after kv is processed, so ids are valid
        grid = self.ids.grid_layout  # the grid id

        for i in range(25):
            button = Button(text=str(i), on_release=self.first_screen)
            grid.add_widget(button)

    def first_screen(self, _):
        app = App.get_running_app() # the app instance
        sm = app.root               # the root widget (ScreenManager)
        sm.current = 'One'


class DynamicButtonApp(App):
    def build(self):
        return Builder.load_string(kv)

DynamicButtonApp().run()
Reply all
Reply to author
Forward
0 new messages