Different rendering for focused or unfocused ScrollablePane

Author: msopacuaCreated Oct 16, 2023Updated Feb 5, 2026

The following code demonstrates a rendering difference between focused and unfocused mode:

python
import asyncio
from time import sleep

from prompt_toolkit.application import Application
from prompt_toolkit.buffer import Buffer
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.layout import ScrollablePane, HSplit, Layout, Window
from prompt_toolkit.layout.controls import BufferControl
from prompt_toolkit.widgets import Frame, TextArea


class Runner:
    def __init__(self):
        self.buffer = Buffer()
        self.buffer_control = BufferControl(buffer=self.buffer)
        self.scrollable_pane = ScrollablePane(
            Window(self.buffer_control, wrap_lines=True), show_scrollbar=True, height=5
        )
        self.text_control = TextArea(
            prompt="Your username: ", multiline=False, password=False
        )
        self.focused_pane = Frame(self.text_control)

        root_container = HSplit([self.scrollable_pane, self.focused_pane])
        self.layout = Layout(root_container)

        self.app = Application(layout=self.layout)

    async def run(self):
        asyncio.create_task(self.update_buffer())
        kb = KeyBindings()

        @kb.add("c-q")
        def _(event) -> None:
            event.app.exit()

        self.layout.focus(self.focused_pane)
        await self.app.run_async()

    async def run_pane_focused(self):
        asyncio.create_task(self.update_buffer())
        kb = KeyBindings()

        @kb.add("c-q")
        def _(event) -> None:
            event.app.exit()

        self.layout.focus(self.scrollable_pane)
        await self.app.run_async()

    async def update_buffer(self):
        count = 0
        while count < 10:
            self.buffer.insert_text(f"New Line {count}\n")
            count += 1
            self.scrollable_pane.vertical_scroll = count
            await asyncio.sleep(1)

        self.app.exit()


if __name__ == "__main__":
    runner = Runner()
    # asyncio.run(runner.run())
    asyncio.run(runner.run_pane_focused())

Toggle the different runner methods to see the difference.

Source: prompt-toolkit/python-prompt-toolkit