mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
blog post (#2465)
* blog posts * fix typo * word * version bump * changelog * update words
This commit is contained in:
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## Unreleased
|
## [0.23.0] - 2023-05-03
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@@ -873,6 +873,7 @@ https://textual.textualize.io/blog/2022/11/08/version-040/#version-040
|
|||||||
- New handler system for messages that doesn't require inheritance
|
- New handler system for messages that doesn't require inheritance
|
||||||
- Improved traceback handling
|
- Improved traceback handling
|
||||||
|
|
||||||
|
[0.23.0]: https://github.com/Textualize/textual/compare/v0.22.3...v0.23.0
|
||||||
[0.22.3]: https://github.com/Textualize/textual/compare/v0.22.2...v0.22.3
|
[0.22.3]: https://github.com/Textualize/textual/compare/v0.22.2...v0.22.3
|
||||||
[0.22.2]: https://github.com/Textualize/textual/compare/v0.22.1...v0.22.2
|
[0.22.2]: https://github.com/Textualize/textual/compare/v0.22.1...v0.22.2
|
||||||
[0.22.1]: https://github.com/Textualize/textual/compare/v0.22.0...v0.22.1
|
[0.22.1]: https://github.com/Textualize/textual/compare/v0.22.0...v0.22.1
|
||||||
|
|||||||
268
docs/blog/images/frogmouth.svg
Normal file
268
docs/blog/images/frogmouth.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 128 KiB |
88
docs/blog/posts/release0-23-0.md
Normal file
88
docs/blog/posts/release0-23-0.md
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
---
|
||||||
|
draft: false
|
||||||
|
date: 2023-05-03
|
||||||
|
categories:
|
||||||
|
- Release
|
||||||
|
title: "Textual 0.23.0 improves message handling"
|
||||||
|
authors:
|
||||||
|
- willmcgugan
|
||||||
|
---
|
||||||
|
|
||||||
|
# Textual 0.23.0 improves message handling
|
||||||
|
|
||||||
|
It's been a busy couple of weeks at Textualize.
|
||||||
|
We've been building apps with [Textual](https://github.com/Textualize/textual), as part of our *dog-fooding* week.
|
||||||
|
The first app, [Frogmouth](https://github.com/Textualize/frogmouth), was released at the weekend and already has 1K GitHub stars!
|
||||||
|
Expect two more such apps this month.
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
<div>
|
||||||
|
--8<-- "docs/blog/images/frogmouth.svg"
|
||||||
|
</div>
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
|
||||||
|
Join our [mailing list](http://eepurl.com/hL0BF1) if you would like to be the first to hear about our apps.
|
||||||
|
|
||||||
|
We haven't stopped developing Textual in that time.
|
||||||
|
Today we released version 0.23.0 which has a really interesting API update I'd like to introduce.
|
||||||
|
|
||||||
|
Textual *widgets* can send messages to each other.
|
||||||
|
To respond to those messages, you implement a message handler with a naming convention.
|
||||||
|
For instance, the [Button](/widget_gallery/#button) widget sends a `Pressed` event.
|
||||||
|
To handle that event, you implement a method called `on_button_pressed`.
|
||||||
|
|
||||||
|
Simple enough, but handler methods are called to handle pressed events from *all* Buttons.
|
||||||
|
To manage multiple buttons you typically had to write a large `if` statement to wire up each button to the code it should run.
|
||||||
|
It didn't take many Buttons before the handler became hard to follow.
|
||||||
|
|
||||||
|
## On decorator
|
||||||
|
|
||||||
|
Version 0.23.0 introduces the [`@on`](/guide/events/#on-decorator) decorator which allows you to dispatch events based on the widget that initiated them.
|
||||||
|
|
||||||
|
This is probably best explained in code.
|
||||||
|
The following two listings respond to buttons being pressed.
|
||||||
|
The first uses a single message handler, the second uses the decorator approach:
|
||||||
|
|
||||||
|
=== "on_decorator01.py"
|
||||||
|
|
||||||
|
```python title="on_decorator01.py"
|
||||||
|
--8<-- "docs/examples/events/on_decorator01.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
1. The message handler is called when any button is pressed
|
||||||
|
|
||||||
|
=== "on_decorator02.py"
|
||||||
|
|
||||||
|
```python title="on_decorator02.py"
|
||||||
|
--8<-- "docs/examples/events/on_decorator02.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Matches the button with an id of "bell" (note the `#` to match the id)
|
||||||
|
2. Matches the button with class names "toggle" *and* "dark"
|
||||||
|
3. Matches the button with an id of "quit"
|
||||||
|
|
||||||
|
=== "Output"
|
||||||
|
|
||||||
|
```{.textual path="docs/examples/events/on_decorator01.py"}
|
||||||
|
```
|
||||||
|
|
||||||
|
The decorator dispatches events based on a CSS selector.
|
||||||
|
This means that you could have a handler per button, or a handler for buttons with a shared class, or parent.
|
||||||
|
|
||||||
|
We think this is a very flexible mechanism that will help keep code readable and maintainable.
|
||||||
|
|
||||||
|
## Why didn't we do this earlier?
|
||||||
|
|
||||||
|
It's a reasonable question to ask: why didn't we implement this in an earlier version?
|
||||||
|
We were certainly aware there was a deficiency in the API.
|
||||||
|
|
||||||
|
The truth is simply that we didn't have an elegant solution in mind until recently.
|
||||||
|
The `@on` decorator is, I believe, an elegant and powerful mechanism for dispatching handlers.
|
||||||
|
It might seem obvious in hindsight, but it took many iterations and brainstorming in the office to come up with it!
|
||||||
|
|
||||||
|
|
||||||
|
## Join us
|
||||||
|
|
||||||
|
If you want to talk about this update or anything else Textual related, join us on our [Discord server](https://discord.gg/Enf6Z3qhVr).
|
||||||
@@ -12,7 +12,7 @@ class OnDecoratorApp(App):
|
|||||||
yield Button("Toggle dark", classes="toggle dark")
|
yield Button("Toggle dark", classes="toggle dark")
|
||||||
yield Button("Quit", id="quit")
|
yield Button("Quit", id="quit")
|
||||||
|
|
||||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
def on_button_pressed(self, event: Button.Pressed) -> None: # (1)!
|
||||||
"""Handle all button pressed events."""
|
"""Handle all button pressed events."""
|
||||||
if event.button.id == "bell":
|
if event.button.id == "bell":
|
||||||
self.bell()
|
self.bell()
|
||||||
|
|||||||
@@ -181,6 +181,8 @@ In the following example we have three buttons, each of which does something dif
|
|||||||
--8<-- "docs/examples/events/on_decorator01.py"
|
--8<-- "docs/examples/events/on_decorator01.py"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
1. The message handler is called when any button is pressed
|
||||||
|
|
||||||
=== "Output"
|
=== "Output"
|
||||||
|
|
||||||
```{.textual path="docs/examples/events/on_decorator01.py"}
|
```{.textual path="docs/examples/events/on_decorator01.py"}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "textual"
|
name = "textual"
|
||||||
version = "0.22.3"
|
version = "0.23.0"
|
||||||
homepage = "https://github.com/Textualize/textual"
|
homepage = "https://github.com/Textualize/textual"
|
||||||
description = "Modern Text User Interface framework"
|
description = "Modern Text User Interface framework"
|
||||||
authors = ["Will McGugan <will@textualize.io>"]
|
authors = ["Will McGugan <will@textualize.io>"]
|
||||||
|
|||||||
Reference in New Issue
Block a user