kainoir

Scroll End - MRE

Jul 7th, 2025 (edited)
8
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.64 KB | None | 0 0
  1. # /// script
  2. # requires-python = ">=3.13"
  3. # dependencies = [
  4. #     "textual",
  5. # ]
  6. # ///
  7.  
  8. """
  9. This is a minimal reproducible example (MRE) to demonstrate a scroll-to-end issue in Textual.
  10. The uv in-file config is used to specify dependencies and Python version, so no separate environment is needed.
  11.  
  12. ## How to Run
  13.  
  14. ### Using uv (recommended):
  15.    uv run scroll_end_textual.py
  16.  
  17. ### Using pip:
  18.    pip install textual
  19.    python scroll_end_textual.py
  20. """
  21.  
  22. from textual.app import App
  23. from textual.containers import ScrollableContainer, Vertical
  24. from textual.widgets import Static
  25.  
  26.  
  27. class SimpleApp(App):
  28.     MAIN = "main"
  29.     CONTENT_WRAPPER = "wrapper"
  30.     INSTRUCTIONS = "Press \[Enter] to add lines, 'c' to clear"
  31.  
  32.     def compose(self):
  33.         yield ScrollableContainer(Vertical(id=self.MAIN), id=self.CONTENT_WRAPPER)
  34.  
  35.     async def add_to_screen(self, widget):
  36.         # This is how widgets are added
  37.         main = self.get_widget_by_id(self.MAIN)
  38.         await main.mount(widget)
  39.         await self.scroll_to_end()
  40.  
  41.     async def scroll_to_end(self):
  42.         # This is the method used to scroll to the end
  43.         container = self.get_widget_by_id(self.CONTENT_WRAPPER)
  44.         container.scroll_end()
  45.  
  46.     # Maintained original styles and application method
  47.  
  48.     async def on_mount(self):
  49.         self._style_content_wrapper()
  50.         self._style_content_area()
  51.  
  52.         await self.add_to_screen(Static(self.INSTRUCTIONS))
  53.  
  54.     def _style_content_wrapper(self):
  55.         container = self.get_widget_by_id(self.CONTENT_WRAPPER)
  56.         container.styles.flex = 1
  57.         container.styles.height = "1fr"
  58.         container.styles.border = None
  59.         container.styles.padding = (1, 1)
  60.         container.styles.overflow_y = "auto"
  61.  
  62.     def _style_content_area(self):
  63.         main = self.get_widget_by_id(self.MAIN)
  64.         main.styles.border = None
  65.         main.styles.padding = (0, 0, 0, 1)
  66.         main.styles.min_height = "100%"
  67.         main.styles.overflow_y = "auto"
  68.  
  69.     # Demonstration Related Methods
  70.  
  71.     async def add_lines(self, n):
  72.         for line_count in range(n):
  73.             await self.add_to_screen(Static(f"Line {line_count + 1}"))
  74.         await self.scroll_to_end()
  75.  
  76.     async def clear_main(self):
  77.         main = self.get_widget_by_id(self.MAIN)
  78.         await main.remove_children()
  79.  
  80.     async def on_key(self, event):
  81.         if event.key == "enter":
  82.             await self.add_lines(20)
  83.         elif event.key == "c":
  84.             await self.clear_main()
  85.             await self.add_to_screen(Static(self.INSTRUCTIONS))
  86.  
  87.  
  88. #
  89. #   Module Run
  90. #
  91. if __name__ == "__main__":
  92.     SimpleApp().run()
  93.  
Advertisement
Add Comment
Please, Sign In to add comment