Merge pull request #1706 from Textualize/document-sub-title

Document setting (sub) title in the app guide
This commit is contained in:
Rodrigo Girão Serrão
2023-02-01 15:08:43 +00:00
committed by GitHub
6 changed files with 98 additions and 11 deletions

View File

@@ -1,10 +1,10 @@
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.widgets import Static, Button from textual.widgets import Label, Button
class QuestionApp(App[str]): class QuestionApp(App[str]):
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
yield Static("Do you love Textual?") yield Label("Do you love Textual?")
yield Button("Yes", id="yes", variant="primary") yield Button("Yes", id="yes", variant="primary")
yield Button("No", id="no", variant="error") yield Button("No", id="no", variant="error")

View File

@@ -1,12 +1,12 @@
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.widgets import Static, Button from textual.widgets import Label, Button
class QuestionApp(App[str]): class QuestionApp(App[str]):
CSS_PATH = "question02.css" CSS_PATH = "question02.css"
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
yield Static("Do you love Textual?", id="question") yield Label("Do you love Textual?", id="question")
yield Button("Yes", id="yes", variant="primary") yield Button("Yes", id="yes", variant="primary")
yield Button("No", id="no", variant="error") yield Button("No", id="no", variant="error")

View File

@@ -1,5 +1,5 @@
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.widgets import Static, Button from textual.widgets import Label, Button
class QuestionApp(App[str]): class QuestionApp(App[str]):
@@ -24,7 +24,7 @@ class QuestionApp(App[str]):
""" """
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
yield Static("Do you love Textual?", id="question") yield Label("Do you love Textual?", id="question")
yield Button("Yes", id="yes", variant="primary") yield Button("Yes", id="yes", variant="primary")
yield Button("No", id="no", variant="error") yield Button("No", id="no", variant="error")

View File

@@ -0,0 +1,22 @@
from textual.app import App, ComposeResult
from textual.widgets import Button, Header, Label
class MyApp(App[str]):
TITLE = "A Question App"
SUB_TITLE = "The most important question"
def compose(self) -> ComposeResult:
yield Header()
yield Label("Do you love Textual?")
yield Button("Yes", id="yes", variant="primary")
yield Button("No", id="no", variant="error")
def on_button_pressed(self, event: Button.Pressed) -> None:
self.exit(event.button.id)
if __name__ == "__main__":
app = MyApp()
reply = app.run()
print(reply)

View File

@@ -0,0 +1,27 @@
from textual.app import App, ComposeResult
from textual.events import Key
from textual.widgets import Button, Header, Label
class MyApp(App[str]):
TITLE = "A Question App"
SUB_TITLE = "The most important question"
def compose(self) -> ComposeResult:
yield Header()
yield Label("Do you love Textual?")
yield Button("Yes", id="yes", variant="primary")
yield Button("No", id="no", variant="error")
def on_button_pressed(self, event: Button.Pressed) -> None:
self.exit(event.button.id)
def on_key(self, event: Key):
self.title = event.key
self.sub_title = f"You just pressed {event.key}!"
if __name__ == "__main__":
app = MyApp()
reply = app.run()
print(reply)

View File

@@ -38,6 +38,7 @@ If you hit ++ctrl+c++ Textual will exit application mode and return you to the c
A side effect of application mode is that you may no longer be able to select and copy text in the usual way. Terminals typically offer a way to bypass this limit with a key modifier. On iTerm you can select text if you hold the ++option++ key. See the documentation for your terminal software for how to select text in application mode. A side effect of application mode is that you may no longer be able to select and copy text in the usual way. Terminals typically offer a way to bypass this limit with a key modifier. On iTerm you can select text if you hold the ++option++ key. See the documentation for your terminal software for how to select text in application mode.
## Events ## Events
Textual has an event system you can use to respond to key presses, mouse actions, and internal state changes. Event handlers are methods 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 prefixed with `on_` followed by the name of the event.
@@ -116,7 +117,7 @@ When you first run this you will get a blank screen. Press any key to add the we
```{.textual path="docs/examples/app/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 ## Exiting
An app will run until you call [App.exit()][textual.app.App.exit] which will exit application mode and the [run][textual.app.App.run] method will return. If this is the last line in your code you will return to the command prompt. An app will run until you call [App.exit()][textual.app.App.exit] which will exit application mode and the [run][textual.app.App.run] method will return. If this is the last line in your code you will return to the command prompt.
@@ -133,7 +134,7 @@ Running this app will give you the following:
Clicking either of those buttons will exit the app, and the `run()` method will return either `"yes"` or `"no"` depending on button clicked. Clicking either of those buttons will exit the app, and the `run()` method will return either `"yes"` or `"no"` depending on button clicked.
#### Return type ### Return type
You may have noticed that we subclassed `App[str]` rather than the usual `App`. You may have noticed that we subclassed `App[str]` rather than the usual `App`.
@@ -147,6 +148,7 @@ The addition of `[str]` tells mypy that `run()` is expected to return a string.
Type annotations are entirely optional (but recommended) with Textual. Type annotations are entirely optional (but recommended) with Textual.
## CSS ## 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). 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).
@@ -170,6 +172,7 @@ When `"question02.py"` runs it will load `"question02.css"` and update the app a
```{.textual path="docs/examples/app/question02.py"} ```{.textual path="docs/examples/app/question02.py"}
``` ```
### Classvar CSS ### Classvar CSS
While external CSS files are recommended for most applications, and enable some cool features like *live editing*, you can also specify the CSS directly within the Python code. While external CSS files are recommended for most applications, and enable some cool features like *live editing*, you can also specify the CSS directly within the Python code.
@@ -182,6 +185,41 @@ Here's the question app with classvar CSS:
--8<-- "docs/examples/app/question03.py" --8<-- "docs/examples/app/question03.py"
``` ```
## Title and subtitle
Textual applications have a `title` attribute that represents the name of your application and a `sub_title` attribute that gives additional context for it.
These attributes can be displayed to the user if your application has a widget `Header` and there are two ways in which you can customize them if you don't want to run with the default values.
By default, the title of your application matches the name of the application class and the subtitle is empty.
However, you can override those defaults by setting the class attributes `TITLE` and `SUB_TITLE`, as shown below.
Remember that you need the built-in widget `Header` to make the title and the subtitle visible in our app.
```py title="question_title01.py" hl_lines="6-7 10"
--8<-- "docs/examples/app/question_title01.py"
```
The app title and subtitle are displayed at the top of the application in the header:
```{.textual path="docs/examples/app/question_title01.py"}
```
On top of being able to define a default title and a default subtitle for a given application class, each _instance_ of your application class has two attributes `title` and `sub_title` that can be used to modify the title and subtitle of said instance application.
For example, the application shown below changes its title and subtitle as soon as the application is instantiated.
```py title="question_title02.py" hl_lines="19-21"
--8<-- "docs/examples/app/question_title02.py"
```
If you run the app shown above and if you press a key, the title and subtitle update accordingly.
For example, if you press ++t++, your application will look as shown below:
```{.textual path="docs/examples/app/question_title02.py" press="t"}
```
## What's next ## What's next
In the following chapter we will learn more about how to apply styles to your widgets and app. In the following chapter we will learn more about how to apply styles to your widgets and app.