pythonclasstextual

Switch mode from inside a screen in Textual library - Python


In Textual, I have an app which has 3 modes. However I want to switch the mode inside a screen based on user input. How do I accomplish that? App.py :

class DemoApp(App[None]):
MODES = {
        "profile": ProfileScreen,
        "chat": ChatScreen,
        "help": HelpScreen,
        }
    def on_mount(self) -> None:
        """On running"""
        LOGGER.info("Starting")
        self.switch_mode("chat")
class ChatScreen(Screen):
    def compose(self) -> ComposeResult:
        yield Button(label="Profile", variant="success", id="change_profile")

    async def on_button_pressed(self) -> None:
        await self.process()

    async def process():
        switch_mode("profile")  # How do I do this?

I searched all over google and read the docs. But I still couldn't find a solution.


Solution

  • You can get the running App instance through the app property, so just:

    async def process(self):
        self.app.switch_mode("profile")
    

    Note that you had forgotten the self argument in the process instance method.


    A reproducible example:

    from textual.app import App, ComposeResult
    from textual.screen import Screen
    from textual.widgets import Button
    
    
    class ChatScreen(Screen):
        def compose(self) -> ComposeResult:
            yield Button(label="Profile", variant="success", id="change_profile")
    
        async def on_button_pressed(self) -> None:
            self.app.switch_mode("profile")
    
    
    class ProfileScreen(Screen):
        def compose(self) -> ComposeResult:
            yield Button(label="Help", variant="success", id="change_profile")
    
        async def on_button_pressed(self) -> None:
            self.app.switch_mode("help")
    
    
    class HelpScreen(Screen):
        def compose(self) -> ComposeResult:
            yield Button(label="Chat", variant="success", id="change_profile")
    
        async def on_button_pressed(self) -> None:
            self.app.switch_mode("chat")
    
    
    class DemoApp(App[None]):
        MODES = {
                "profile": ProfileScreen,
                "chat": ChatScreen,
                "help": HelpScreen,
                }
    
        def on_mount(self) -> None:
            """On running"""
            # LOGGER.info("Starting")
            self.switch_mode("chat")
    
    
    if __name__ == "__main__":
        app = DemoApp()
        app.run()