Skip to content

Commit e987974

Browse files
committed
Sample code for the article on Textual
1 parent d2f0c94 commit e987974

19 files changed

+376
-0
lines changed

python-textual/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Python Textual: Build Beautiful UIs in the Terminal
2+
3+
This folder provides the code examples for the Real Python tutorial [Python Textual: Build Beautiful UIs in the Terminal](https://realpython.com/python-textual/).
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from textual.app import App
2+
from textual.widgets import Button, Input
3+
4+
class ButtonsAndInputsApp(App):
5+
def compose(self):
6+
# Buttons
7+
yield Button("Click me!")
8+
yield Button("Primary!", variant="primary")
9+
yield Button.success("Success!")
10+
yield Button.warning("Warning!")
11+
yield Button.error("Error!")
12+
# Inputs
13+
yield Input(placeholder="Type your text here")
14+
yield Input(placeholder="Password", password=True)
15+
yield Input(
16+
placeholder="Type a number here",
17+
type="number",
18+
tooltip="Digits only please!",
19+
)
20+
21+
if __name__ == "__main__":
22+
app = ButtonsAndInputsApp()
23+
app.run()

python-textual/events.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# from textual import on
2+
from textual.app import App
3+
from textual.widgets import Button, Digits, Footer
4+
5+
class EventsApp(App):
6+
CSS_PATH = "events.tcss"
7+
BINDINGS = [
8+
("q", "quit", "Quit"),
9+
("b", "toggle_border", "Toggle border"),
10+
]
11+
12+
presses_count = 0
13+
double_border = False
14+
15+
def compose(self):
16+
yield Button(
17+
"Click me!",
18+
id="button",
19+
)
20+
digits = Digits("0", id="digits")
21+
digits.border_subtitle = "Button presses"
22+
yield digits
23+
yield Footer()
24+
25+
def action_toggle_border(self):
26+
self.double_border = not self.double_border
27+
digits = self.query_one("#digits")
28+
if self.double_border:
29+
digits.styles.border = ("double", "yellow")
30+
else:
31+
digits.styles.border = ("solid", "white")
32+
33+
def on_button_pressed(self, event):
34+
if event.button.id == "button":
35+
self.presses_count += 1
36+
digits = self.query_one("#digits")
37+
digits.update(f"{self.presses_count}")
38+
39+
# @on(Button.Pressed, "#button")
40+
# def button_pressed(self, event):
41+
# self.presses_count += 1
42+
# digits = self.query_one("#digits")
43+
# digits.update(f"{self.presses_count}")
44+
45+
if __name__ == "__main__":
46+
app = EventsApp()
47+
app.run()

python-textual/events.tcss

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Button {
2+
background: $secondary;
3+
border: solid $primary;
4+
margin: 2 2;
5+
}
6+
7+
Button:hover {
8+
border: round white;
9+
}
10+
11+
#digits {
12+
color: green;
13+
border: solid white;
14+
padding: 1;
15+
width: 30;
16+
}

python-textual/grid.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from textual.app import App
2+
from textual.containers import Grid
3+
from textual.widgets import Static
4+
5+
class GridLayoutExample(App):
6+
def compose(self):
7+
grid = Grid()
8+
grid.styles.grid_size_rows = rows = 6
9+
grid.styles.grid_size_columns = cols = 4
10+
with grid:
11+
for row in range(rows):
12+
for col in range(cols):
13+
static = Static(f"Static ({row=}, {col=})")
14+
static.styles.border = ("solid", "green")
15+
static.styles.width = "1fr"
16+
static.styles.height = "1fr"
17+
yield static
18+
19+
if __name__ == "__main__":
20+
app = GridLayoutExample()
21+
app.run()

python-textual/grid.tcss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Grid {
2+
grid_size: 4 6;
3+
}
4+
5+
Static {
6+
height: 1fr;
7+
width: 1fr;
8+
border: solid green;
9+
}

python-textual/grid_with_tcss.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from textual.app import App
2+
from textual.containers import Grid
3+
from textual.widgets import Static
4+
5+
class GridLayoutWithTCSS(App):
6+
CSS_PATH = "grid.tcss"
7+
8+
def compose(self):
9+
with Grid():
10+
for row in range(6):
11+
for col in range(4):
12+
yield Static(f"Static ({row=}, {col=})")
13+
14+
if __name__ == "__main__":
15+
app = GridLayoutWithTCSS()
16+
app.run()

python-textual/hello_textual.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from textual.app import App
2+
from textual.widgets import Static
3+
4+
class HelloTextualApp(App):
5+
def compose(self):
6+
yield Static("Hello, Textual!")
7+
8+
if __name__ == "__main__":
9+
app = HelloTextualApp()
10+
app.run()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from textual.app import App
2+
from textual.containers import Horizontal
3+
from textual.widgets import Static
4+
5+
NUM_BOXES = 4
6+
7+
class HorizontalLayoutExample(App):
8+
def compose(self):
9+
with Horizontal():
10+
for i in range(NUM_BOXES):
11+
static = Static(f"Static {i+1}")
12+
static.styles.border = ("solid", "green")
13+
static.styles.width="10%"
14+
yield static
15+
16+
if __name__ == "__main__":
17+
app = HorizontalLayoutExample()
18+
app.run()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from textual.app import App
2+
from textual.containers import HorizontalScroll
3+
from textual.widgets import Static
4+
5+
NUM_BOXES = 20
6+
7+
class HorizontalScrollExample(App):
8+
def compose(self):
9+
with HorizontalScroll():
10+
for i in range(NUM_BOXES):
11+
static = Static(f"Static {i+1}")
12+
static.styles.border = ("solid", "green")
13+
static.styles.width="10%"
14+
yield static
15+
16+
if __name__ == "__main__":
17+
app = HorizontalScrollExample()
18+
app.run()

0 commit comments

Comments
 (0)