Skip to content

Instantly share code, notes, and snippets.

@holdenweb
Created January 22, 2025 18:15
Show Gist options
  • Save holdenweb/08feacdc0779cd6fde9a695f3273cb7d to your computer and use it in GitHub Desktop.
Save holdenweb/08feacdc0779cd6fde9a695f3273cb7d to your computer and use it in GitHub Desktop.
Little test program to report event bubbling in Textual
"""
TextualMessageOrder.py: Little tool to demonstrate the order in which
message handlers are invoked in Textual, through both the class hierarchy and
the DOM structure.
In particular, observe that although Subclass's on_click method will override
Superclass's on a normal method call, in processing events both methods are
called, ascending the class hierarchy.
To most clearly observe the sequence of events run a filtering console to
show only messages of class INFO:
textual console -x SYSTEM -x WARNING -x ERROR -x PRINT -x DEBUG -x EVENT
then in a separate window run this program with
textual run --dev TextualMessagingOrder.py
Clicking on different containers will show different subsets of handlers
being called.
"""
from time import time
from textual import on
from textual.app import App
from textual import on
from textual.containers import Horizontal
from textual.containers import VerticalScroll
from textual.containers import Vertical
from textual.message import Message
from textual.widgets import Label
start_time = time()
def tt():
return f"{time() - start_time:8.6f}"
class Superclass(Vertical):
"""
A class that responds to clicks.
"""
def on_click(self, event):
msg = f"{tt()} Superclass {self.id}"
self.app.message.mount(Label(msg))
class Subclass(Superclass):
"""
A subclass which also responds to clicks.
"""
def on_click(self, event):
msg = f"{tt()} Subclass {self.id}"
self.app.message.mount(Label(msg))
class TestApp(App):
DEFAULT_CSS = """
#outer, #inner {
height: auto;
border: solid blue;
width: 1fr;
}
#middle {
border: dashed blue;
height: auto;
}
#self-message {
border: solid red;
height: auto;
}
"""
def compose(self):
self.message = VerticalScroll(id="self-message")
with self.message:
yield Subclass(
Superclass(Subclass(Label("Click Somewhere"), id="inner"), id="middle"),
id="outer",
)
def on_click(self, event):
"Indicate that the click hits the DOM root."
self.app.message.mount(Label("-" * 72))
TestApp().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment