Using the library
Including the widget
textual-countdown
provides just one widget:
Countdown
; this can be composed into your
application like any other widget:
from textual.app import App, ComposeResult
from textual_countdown import Countdown
class CountdownApp(App[None]):
def compose(self) -> ComposeResult:
yield Countdown()
if __name__ == "__main__":
CountdownApp().run()
Starting a countdown
As you can see above, the Countdown
widget
doesn't do anything interesting to start with; it's just a dim line. To have
the widget start to count down and show the user that something is happening
you need to call the start
method:
from textual.app import App, ComposeResult
from textual_countdown import Countdown
class CountdownApp(App[None]):
def compose(self) -> ComposeResult:
yield Countdown()
def on_mount(self) -> None:
self.query_one(Countdown).start(10)
if __name__ == "__main__":
CountdownApp().run()
Once the countdown starts, as you can see above in the tab that shows the result, the countdown bar will change colour to show how much time is left to go. Over time the highlighted portion of the bar will reduce:
Knowing when the countdown starts and ends
To help react to a countdown starting and ending the
Countdown
widget posts two different
messages:
Started
and
Finished
.
from textual import on
from textual.app import App, ComposeResult
from textual_countdown import Countdown
class CountdownApp(App[None]):
def compose(self) -> ComposeResult:
yield Countdown()
def on_mount(self) -> None:
self.query_one(Countdown).start(2)
@on(Countdown.Started)
def _react_to_start(self) -> None:
self.notify("The countdown has begun!")
@on(Countdown.Finished)
def _react_to_finish(self) -> None:
self.notify("The countdown has ended!")
if __name__ == "__main__":
CountdownApp().run()
Cancelling a countdown
There are going to be times when you want to cancel a running countdown,
this can be done with the cancel
method. If called the countdown will stop, the display will revert back to
the "not running" appearance, and a
Cancelled
message is posted.
from textual import on
from textual.app import App, ComposeResult
from textual_countdown import Countdown
class CountdownApp(App[None]):
def compose(self) -> ComposeResult:
yield Countdown()
def on_mount(self) -> None:
self.query_one(Countdown).start(3)
self.set_timer(1, self.query_one(Countdown).cancel)
@on(Countdown.Cancelled)
def _react_to_cancel(self) -> None:
self.notify("The countdown was cancelled!")
if __name__ == "__main__":
CountdownApp().run()
Styling the countdown widget
The background of the widget is styled using the usual Textual background
style. Likewise, the
"non-counting" portion of the bar is controlled with the usual Textual
color
style.
To style the time-remaining portion of the bar of a running countdown, use
the countdown--remaining
component class:
from textual.app import App, ComposeResult
from textual_countdown import Countdown
class CountdownApp(App[None]):
CSS = """
Countdown {
background: red;
color: blue;
&> .countdown--remaining {
color: yellow;
}
}
"""
def compose(self) -> ComposeResult:
yield Countdown()
def on_mount(self) -> None:
self.query_one(Countdown).start(3)
if __name__ == "__main__":
CountdownApp().run()