mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
renamed introduction to tutorial
This commit is contained in:
@@ -10,7 +10,7 @@ CSS stands for _Cascading Stylesheets_. A stylesheet is a list of styles and rul
|
||||
|
||||
Depending on what you want to build with Textual, you may not need to learn Textual CSS at all. Widgets are packaged with CSS styles so apps with exclusively pre-built widgets may not need any additional CSS.
|
||||
|
||||
Textual CSS defines a set of rules which apply visual _styles_ to your application and widgets. These style can customize a large variety of visual settings, such as color, border, size, alignment; and more dynamic features such as animation and hover effects. As powerful as it is, CSS in Textual is quite straightforward.
|
||||
Textual CSS defines a set of rules which apply visual _styles_ to your application and widgets. These style can customize settings for properties such as color, border, size, alignment; and more dynamic features such as animation and hover effects. As powerful as it is, CSS in Textual is quite straightforward.
|
||||
|
||||
CSS is typically stored in an external file with the extension `.css` alongside your Python code.
|
||||
|
||||
@@ -30,7 +30,7 @@ This is an example of a CSS _rule set_. There may be many such sections in any g
|
||||
|
||||
Let's break this CSS code down a bit.
|
||||
|
||||
```css hl_lines="1"
|
||||
```sass hl_lines="1"
|
||||
Header {
|
||||
dock: top;
|
||||
height: 3;
|
||||
@@ -42,7 +42,7 @@ Header {
|
||||
|
||||
The first line is a _selector_ which tells Textual which Widget(s) to modify. In the above example, the styles will be applied to a widget defined by the Python class `Header`.
|
||||
|
||||
```css hl_lines="2 3 4 5 6"
|
||||
```sass hl_lines="2 3 4 5 6"
|
||||
Header {
|
||||
dock: top;
|
||||
height: 3;
|
||||
@@ -58,7 +58,7 @@ The first rule in the above example reads `"dock: top;"`. The rule name is `dock
|
||||
|
||||
## The DOM
|
||||
|
||||
The DOM, or _Document Object Model_, is a term borrowed from the web world. Textual doesn't use documents but the term has stuck. In Textual CSS, the DOM is a an arrangement of widgets you can visualize as a tree-like structure.
|
||||
The DOM, or _Document Object Model_, is a term borrowed from the web world. Textual doesn't use documents but the term has stuck. In Textual CSS, the DOM is an arrangement of widgets you can visualize as a tree-like structure.
|
||||
|
||||
Some widgets contain other widgets: for instance, a list control widget will likely also have item widgets, or a dialog widget may contain button widgets. These _child_ widgets form the branches of the tree.
|
||||
|
||||
|
||||
1
docs/guide/actions.md
Normal file
1
docs/guide/actions.md
Normal file
@@ -0,0 +1 @@
|
||||
# Actions
|
||||
@@ -1,6 +1,6 @@
|
||||
# App Basics
|
||||
|
||||
In this chapter we will cover what you will need to know to build a Textual application. Just enough to get you up to speed. We will go in to more detail in the following chapters.
|
||||
In this chapter we will cover how to use Textual's App class to create an application. Just enough to get you up to speed. We will go in to more detail in the following chapters.
|
||||
|
||||
## The App class
|
||||
|
||||
@@ -26,20 +26,24 @@ Apps don't get much simpler than this—don't expect it to do much.
|
||||
|
||||
If we run this app with `python simple02.py` you will see a blank terminal, something like the following:
|
||||
|
||||
```{.textual path="docs/examples/app/simple02.py" title="simple02.py"}
|
||||
```{.textual path="docs/examples/app/simple02.py"}
|
||||
```
|
||||
|
||||
When you call [App.run()][textual.app.App.run] Textual puts the terminal in to a special state called *application mode*. When in application mode, the terminal will no longer echo what you type. Textual will take over responding to user input (keyboard and mouse) and will update the visible portion of the terminal (i.e. the *screen*).
|
||||
When you call [App.run()][textual.app.App.run] Textual puts the terminal in to a special state called *application mode*. When in application mode the terminal will no longer echo what you type. Textual will take over responding to user input (keyboard and mouse) and will update the visible portion of the terminal (i.e. the *screen*).
|
||||
|
||||
If you hit ++ctrl+c++ Textual will exit application mode and return you to the command prompt. Any content you had in the terminal prior to application mode will be restored.
|
||||
|
||||
## Events
|
||||
|
||||
Textual has an event system you can use to respond to key presses, mouse actions, and also internal state changes. Event handlers are methods which are prefixed with `on_` followed by the name of the event.
|
||||
Textual has an event system you can use to respond to key presses, mouse actions, and internal state changes. Event handlers are methods which are prefixed with `on_` followed by the name of the event.
|
||||
|
||||
One such event is the *mount* event which is sent to an application after it enters application mode. You can respond to this event by defining a method called `on_mount`.
|
||||
|
||||
Another such event is `on_key` which is sent when the user presses a key. The following example contains handlers for both those events:
|
||||
!!! info
|
||||
|
||||
You may have noticed we use the term "send" and "sent" in relation to event handler methods in preference to "calling". This is because Textual uses a message passing system where events are passed (or *sent*) between components. We will cover the details in [events][events.md].
|
||||
|
||||
Another such event is the *key* event which is sent when the user presses a key. The following example contains handlers for both those events:
|
||||
|
||||
```python title="event01.py"
|
||||
--8<-- "docs/examples/app/event01.py"
|
||||
@@ -50,21 +54,21 @@ The `on_mount` handler sets the `self.styles.background` attribute to `"darkblue
|
||||
```{.textual path="docs/examples/app/event01.py" hl_lines="23-25"}
|
||||
```
|
||||
|
||||
The key event handler (`on_key`) specifies an `event` parameter which should be a [events.Key][textual.events.Key] instance. Every event has an associated event object which will be passed to the handler method if it is present in the method's parameter list.
|
||||
The key event handler (`on_key`) specifies an `event` parameter which will receive a [events.Key][textual.events.Key] instance. Every event has an associated event object which will be passed to the handler method if it is present in the method's parameter list.
|
||||
|
||||
!!! note
|
||||
|
||||
It is unusual for a method's parameters to affect how it is called. Textual accomplishes this by inspecting the method prior to calling it.
|
||||
It is unusual (but not unprecedented) for a method's parameters to affect how it is called. Textual accomplishes this by inspecting the method prior to calling it.
|
||||
|
||||
For some events, such as the key event, there is additional information on the event object. In the case of [events.Key][textual.events.Key] it will contain the key that was pressed.
|
||||
For some events, such as the key event, the event object contains additional information. In the case of [events.Key][textual.events.Key] it will contain the key that was pressed.
|
||||
|
||||
The `on_key` method above uses the `key` attribute on the Key event to change the background color if any of the keys 0-9 are pressed.
|
||||
The `on_key` method above uses the `key` attribute on the Key event to change the background color if any of the keys ++0++ to ++9++ are pressed.
|
||||
|
||||
### Async events
|
||||
|
||||
Textual is powered by Python's [asyncio](https://docs.python.org/3/library/asyncio.html) framework which uses the `async` and `await` keywords to coordinate events.
|
||||
|
||||
Textual knows to *await* your event handlers if they are generators (i.e. prefixed with the `async` keywords).
|
||||
Textual knows to *await* your event handlers if they are generators (i.e. prefixed with the `async` keyword).
|
||||
|
||||
!!! note
|
||||
|
||||
@@ -88,10 +92,10 @@ The following example imports a builtin Welcome widget and yields it from compos
|
||||
|
||||
When you run this code, Textual will *mount* the Welcome widget which contains a Markdown content area and a button:
|
||||
|
||||
```{.textual path="docs/examples/app/widgets01.py" title="widgets01.py" }
|
||||
```{.textual path="docs/examples/app/widgets01.py"}
|
||||
```
|
||||
|
||||
Notice the `on_button_pressed` method which handles the [Button.Pressed][textual.widgets.Button] event send by the button contained in the Welcome widget. The handlers calls [App.exit()][textual.app.App] to exit the app.
|
||||
Notice the `on_button_pressed` method which handles the [Button.Pressed][textual.widgets.Button] event sent by a button contained in the Welcome widget. The handler calls [App.exit()][textual.app.App] to exit the app.
|
||||
|
||||
### Mounting
|
||||
|
||||
@@ -105,7 +109,7 @@ Here's an app which adds the welcome widget in response to any key press:
|
||||
|
||||
When you first run this you will get a blank screen. Press any key to add the welcome widget. You can even press a key multiple times to add several widgets.
|
||||
|
||||
```{.textual path="docs/examples/app/widgets02.py" title="widgets02.py" press="a,a,a,down,down,down,down,down,down,_,_,_,_,_,_"}
|
||||
```{.textual path="docs/examples/app/widgets02.py" press="a,a,a,down,down,down,down,down,down,_,_,_,_,_,_"}
|
||||
```
|
||||
|
||||
### Exiting
|
||||
@@ -138,3 +142,36 @@ The addition of `[str]` tells Mypy that `run()` is expected to return a string.
|
||||
!!! note
|
||||
|
||||
Type annotations are entirely optional (but recommended) with Textual.
|
||||
|
||||
## CSS
|
||||
|
||||
Textual apps can reference [CSS](CSS.md) files which define how your app and widgets will look, while keeping your Python code free of display related code (which tends to be messy).
|
||||
|
||||
The following chapter on [Textual CSS](CSS.md) will describe how to use CSS in detail. For now lets look at how your app references external CSS files.
|
||||
|
||||
The following example sets the `css_path` attribute on the app:
|
||||
|
||||
```python title="question02.py" hl_lines="15"
|
||||
--8<-- "docs/examples/app/question02.py"
|
||||
```
|
||||
|
||||
If the path is relative (as it is above) then it is taken as relative to where the app is defined. Hence this example references `"question01.css"` in the same directory as the Python code. Here is that CSS file:
|
||||
|
||||
```sass title="question02.css"
|
||||
--8<-- "docs/examples/app/question02.css"
|
||||
```
|
||||
|
||||
When `"question02.py"` runs it will load `"question02.css"` and update the app and widgets accordingly. Even though the code is almost identical to the previous sample, the app now looks quite different:
|
||||
|
||||
```{.textual path="docs/examples/app/question02.py"}
|
||||
```
|
||||
|
||||
### Classvar CSS
|
||||
|
||||
While external CSS files are recommended for most applications, and enable some cool features like *live editing* (see below), you can also specify the CSS directly within the Python code. To do this you can set the `CSS` class variable on the app which contains the CSS content.
|
||||
|
||||
Here's the question app with classvar CSS:
|
||||
|
||||
```python title="question03.py" hl_lines="6-24"
|
||||
--8<-- "docs/examples/app/question03.py"
|
||||
```
|
||||
|
||||
@@ -27,7 +27,7 @@ textual run my_app.py
|
||||
|
||||
The `run` sub-command assumes you have an App instance called `app` in the global scope of your Python file. If the application is called something different, you can specify it with a colon following the filename:
|
||||
|
||||
```
|
||||
```bash
|
||||
textual run my_app.py:alternative_app
|
||||
```
|
||||
|
||||
@@ -35,9 +35,22 @@ textual run my_app.py:alternative_app
|
||||
|
||||
If the Python file contains a call to app.run() then you can launch the file as you normally would any other Python program. Running your app via `textual run` will give you access to a few Textual features such as live editing of CSS files.
|
||||
|
||||
|
||||
## Live editing
|
||||
|
||||
If you combine the `run` command with the `--dev` switch your app will run in *development mode*.
|
||||
|
||||
```bash
|
||||
textual run --dev my_app.py
|
||||
```
|
||||
|
||||
One of the the features of *dev* mode is live editing of CSS files: any changes to your CSS will be reflected in the terminal a few milliseconds later.
|
||||
|
||||
This is a great feature for iterating on your app's look and feel. Open the CSS in your editor and have your app running in a terminal. Edits to your CSS will appear almost immediately after you save.
|
||||
|
||||
## Console
|
||||
|
||||
When running a terminal application, you will generally no longer be able to use `print` when debugging (or log to the console). This is because anything you write to standard output would overwrite application content, making it unreadable. Fortunately Textual supplies a debug console of its own which has some super helpful features.
|
||||
When building a typical terminal application you are generally unable to use `print` when debugging (or log to the console). This is because anything you write to standard output will overwrite application content. Textual has a solution to this in the form of a debug console which restores `print` and adds a few additional features to help you debug.
|
||||
|
||||
To use the console, open up **two** terminal emulators. Run the following in one of the terminals:
|
||||
|
||||
@@ -58,6 +71,7 @@ textual run --dev my_app.py
|
||||
|
||||
Anything you `print` from your application will be displayed in the console window. Textual will also write log messages to this window which may be helpful when debugging your application.
|
||||
|
||||
|
||||
### Verbosity
|
||||
|
||||
Textual writes log messages to inform you about certain events, such as when the user presses a key or clicks on the terminal. To avoid swamping you with too much information, some events are marked as "verbose" and will be excluded from the logs. If you want to see these log messages, you can add the `-v` switch.
|
||||
@@ -91,7 +105,7 @@ log("[bold red]DANGER![/] We're having too much fun")
|
||||
|
||||
### Log method
|
||||
|
||||
There's a convenient shortcut to `log` available on the App and Widget objects you can use in event handlers:
|
||||
There's a convenient shortcut to `log` available on the App and Widget objects. This is useful in event handlers. Here's an example:
|
||||
|
||||
```python
|
||||
from textual.app import App
|
||||
|
||||
1
docs/guide/reactivity.md
Normal file
1
docs/guide/reactivity.md
Normal file
@@ -0,0 +1 @@
|
||||
# Reactivity
|
||||
1
docs/guide/screens.md
Normal file
1
docs/guide/screens.md
Normal file
@@ -0,0 +1 @@
|
||||
# Screens
|
||||
1
docs/guide/widgets.md
Normal file
1
docs/guide/widgets.md
Normal file
@@ -0,0 +1 @@
|
||||
# Widgets
|
||||
Reference in New Issue
Block a user