diff --git a/docs/examples/introduction/intro02.py b/docs/examples/introduction/intro02.py index 514029ebb..2f5d3ed64 100644 --- a/docs/examples/introduction/intro02.py +++ b/docs/examples/introduction/intro02.py @@ -22,7 +22,6 @@ class ExampleApp(App): def on_key(self, event): if event.key.isdigit(): self.styles.background = self.COLORS[int(event.key)] - self.refresh() self.bell() diff --git a/docs/introduction.md b/docs/introduction.md index 48065ab7e..749cf9eca 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -11,8 +11,6 @@ By the end of this page you should have a good idea of the steps involved in cre — **Will McGugan** (creator of Rich and Textual) - - ## Stopwatch Application We're going to build a stopwatch application. It should show a list of stopwatches with a time display the user can start, stop, and reset. We also want the user to be able to add and remove stopwatches as required. @@ -37,17 +35,18 @@ python stopwatch.py ## Type hints (in brief) -We're a big fan of Python type hints at Textualize. If you haven't encountered type hinting, its a way to express the types of your data, parameters, and returns. Type hinting allows tools like [Mypy](https://mypy.readthedocs.io/en/stable/) to catch potential bugs before your code runs. +We're a big fan of Python type hints at Textualize. If you haven't encountered type hinting, its a way to express the types of your data, parameters, and return values. Type hinting allows tools like [Mypy](https://mypy.readthedocs.io/en/stable/) to catch potential bugs before your code runs. The following function contains type hints: ```python def repeat(text: str, count: int) -> str: + """Repeat a string a given number of times.""" return text * count ``` -- Parameter types follow a colon, so `text: str` means that `text` should be a string and `count: int` means that `count` should be an integer. -- Return types follow `->` So `-> str:` says that this method returns a string. +- Parameter types follow a colon. So `text: str` indicates that `text` requires a string and `count: int` means that `count` requires an integer. +- Return types follow `->`. So `-> str:` indicates that this method returns a string. !!! note @@ -56,7 +55,7 @@ def repeat(text: str, count: int) -> str: ## The App class -The first step in building a Textual app is to import and extend the `App` class. Here's our basic app class with a few methods which we will cover below. +The first step in building a Textual app is to import and extend the `App` class. Here's our basic app class with a few methods we will cover below. ```python title="stopwatch01.py" --8<-- "docs/examples/introduction/stopwatch01.py" @@ -104,14 +103,14 @@ There are three methods in our stopwatch app currently. !!! note - You may have noticed that the the `toggle_dark` doesn't do anything to explicitly change the _screen_, and yet hitting ++d++ refreshes and updates the whole terminal. This is an example of _reactivity_. Changing certain attributes will schedule an automatic update. + You may have noticed that `action_toggle_dark` doesn't do anything to explicitly change the _screen_, and yet hitting ++d++ updates the terminal. Textual is able to detect changes that should update the screen. ```python title="stopwatch01.py" hl_lines="22-24" --8<-- "docs/examples/introduction/stopwatch01.py" ``` -The last lines in "stopwatch01.py" may be familiar to you. We create an instance of our app class, and call `run()` within a `__name__ == "__main__"` conditional block. This is so that we could import `app` if we want to. Or we could run it with `python stopwatch01.py`. +The last few lines create an instance of the app at the module scope. Followed by a call to `run()` within a `__name__ == "__main__"` block. This is so that we could import `app` if we want to. Or we could run it with `python stopwatch01.py`. ## Designing a UI with widgets @@ -125,12 +124,12 @@ Let's sketch out a design for our app: We will need to build a `Stopwatch` widget composed of the following _child_ widgets: -- A "start" button -- A "stop" button -- A "reset" button +- A "Start" button +- A "Stop" button +- A "Reset" button - A time display -Textual has a builtin `Button` widgets which takes care of the first three components. All we need to build is the time display which will show the elapsed time in HOURS:MINUTES:SECONDS format, and the stopwatch itself. +Textual has a builtin `Button` widget which takes care of the first three components. All we need to build is the time display widget which will show the elapsed time in HOURS:MINUTES:SECONDS format, and the stopwatch widget itself. Let's add those to the app. Just a skeleton for now, we will add the rest of the features as we go. @@ -144,9 +143,9 @@ We've imported two new widgets in this code: `Button`, which creates a clickable We're extending Static as a foundation for our `TimeDisplay` widget. There are no methods on this class yet. -The Stopwatch class also extends Static to define a new widget. This class has a `compose()` method which yields its child widgets, consisting of of three `Button` objects and a single `TimeDisplay`. These are all we need to build a stopwatch as in the sketch. +The Stopwatch class also extends Static to define a new widget. This class has a `compose()` method which yields its child widgets, consisting of three `Button` objects and a single `TimeDisplay`. These are all we need to build a stopwatch as in the sketch. -The Button constructor takes a label to be displayed in the button ("Start", "Stop", or "Reset"). There are two additional parameters to the Button constructor we are using: +The Button constructor takes a label to be displayed in the button ("Start", "Stop", or "Reset"). Additionally some of the buttons set the following parameters: - **`id`** is an identifier we can use to tell the buttons apart in code and apply styles. More on that later. - **`variant`** is a string which selects a default style. The "success" variant makes the button green, and the "error" variant makes it red. @@ -155,7 +154,7 @@ The Button constructor takes a label to be displayed in the button ("Start", "St To see our widgets with we first need to yield them from the app's `compose()` method: -The new line in `Stopwatch.compose()` yields a single `Container` object which will create a scrolling list. When classes contain other widgets (like `Container`) they will typically accept their child widgets as positional arguments. We want to start the app with three stopwatches, so we construct three `Stopwatch` instances as child widgets of the container. +The new line in `Stopwatch.compose()` yields a single `Container` object which will create a scrolling list of stopwatches. When classes contain other widgets (like `Container`) they will typically accept their child widgets as positional arguments. We want to start the app with three stopwatches, so we construct three `Stopwatch` instances and pass them to the container's constructor. ### The unstyled app @@ -165,13 +164,11 @@ Let's see what happens when we run "stopwatch02.py". ```{.textual path="docs/examples/introduction/stopwatch02.py" title="stopwatch02.py"} ``` -The elements of the stopwatch application are there. The buttons are clickable and you can scroll the container, but it doesn't look much like the sketch. This is because we have yet to apply any _styles_ to our new widget. +The elements of the stopwatch application are there. The buttons are clickable and you can scroll the container but it doesn't look like the sketch. This is because we have yet to apply any _styles_ to our new widgets. ## Writing Textual CSS -Every widget has a `styles` object which contains information regarding how that widget will look. Setting any of the attributes on the styles object will update the screen. - -Here's how you might set white text and a blue background for a widget: +Every widget has a `styles` object with a number of attributes that impact how the widget will appear. Here's how you might set white text and a blue background for a widget: ```python self.styles.background = "blue" @@ -221,7 +218,7 @@ Stopwatch { The first line tells Textual that the styles should apply to the `Stopwatch` widget. The lines between the curly brackets contain the styles themselves. -Here's how the Stopwatch block in the CSS impacts our `Stopwatch` widget: +Here's how this CSS code changes how the `Stopwatch` widget is displayed.